当前位置 : 首页 » 文章分类 :  开发  »  JavaScript-基础

JavaScript-基础

JavaScript 学习笔记
Jeff Atwood 在 2007 年提出 ​​Atwood 定律(Atwood’s Law)

Any application that can be written in JavaScript, will eventually be written in JavaScript.
任何能够用 JavaScript 实现的应用系统,最终都必将用 JavaScript 实现。

在线执行代码
https://tool.lu/coderunner/

廖雪峰JavaScript教程
https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000

Mozilla MDN JS教程
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript


变量

全局变量

全局变量 (Global Variables)
定义:在函数或代码块 ​​外部​​ 声明的变量(使用 var、let、const),或未声明直接赋值的变量
作用域​​:整个脚本可用,包括所有函数和代码块。
生命周期​​:页面关闭时销毁。
风险​​:过度使用会导致命名冲突和代码污染(例如第三方库同名变量覆盖)。

var globalVar = "全局变量"; // 全局变量
let globalLet = "也是全局变量"; // 全局作用域,但不在 window 对象上
unDeclared = "未声明的变量"; // 自动成为全局变量(不推荐!)

局部变量

局部变量 (Local Variables)

函数作用域 (Function Scope):用 var 在 ​​函数内部​​ 声明的变量

function example() {
  var localVar = "局部变量"; // 仅在函数内有效
  console.log(localVar); // ✅
}
console.log(localVar); // ❌ 报错:未定义

块级作用域 (Block Scope - ES6):用 let/const 在 ​​{} 代码块内​​(如 if、for)声明的变量

if (true) {
  let blockLet = "块级变量"; 
  const blockConst = "块级常量";
}
console.log(blockLet); // ❌ 报错:未定义

在全局作用域中声明变量可以省略 var 关键字。
默认非严格模式下,在函数体内声明变量时如果不使用 var 关键字会隐式声明为全局变量,即使该语句是在一个 function 内,当该 function 被执行后就变成了全局变量

variable = 'global';

function checkVariable() {
    variable = 'local';
    console.log(variable); // local
    myVariable = 'local';
    console.log(myVariable); // local
}

checkVariable();

console.log(variable); // local
console.log(myVariable); // local

所以:
声明局部变量一定要使用 var 关键字,使用 var 关键字声明变量时,变量会自动添加到距离最近的可用环境中。如果没有写 var, 变量就会暴露在全局上下文中, 这样很可能会和现有变量冲突

编写可维护的JavaScript-全局变量
https://segmentfault.com/a/1190000021219901


use strict 严格模式

JavaScript 的 ​​严格模式(Strict Mode)​​ 是 ECMAScript 5(ES5)引入的重要特性,它通过更严格的语法和运行时规则来约束代码行为,帮助开发者避免常见的错误,提升代码的安全性和可维护性。

在脚本或函数顶部添加 "use strict"; 即可启用严格模式

// 整个脚本启用
"use strict";
let x = 10; // 正确

// 单个函数启用
function strictFunc() {
  "use strict";
  y = 20; // 报错:未声明变量
}

字符串

模板字符串

模板字符串使用反引号 (键盘左上角波浪线下面的字符) 来代替普通字符串中的用双引号和单引号。
模板字符串可以包含特定语法( ${expression} )的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来。
在模版字符串内使用反引号时,需要在它前面加转义符(\)

如果有很多变量需要连接,用+号就比较麻烦。ECMAScript 6(ES 6) 新增了一种模板字符串,表示方法和上面的多行字符串一样,但是它会自动替换字符串中的变量:
例如拼接当前页面的链接:

var pageRef = `<a href="${window.location.protocol}//${window.location.host}${window.location.pathname}">当前页面链接</a>`
var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}岁了!`;
alert(message);

字符串判空

if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
  var variable2 = variable1;
}

字符串等值比较

JavaScript 有两种相等运算符:
1、一种是完全向后兼容的,标准的 ==,如果两个操作数类型不一致,它会在某些时候自动对操作数进行类型转换,考虑下面的赋值语句:

var strA = "i love you!";
var strB = new String("i love you!");

这两个变量含有相同的字符序列,但数据类型却不同,前者为string,后者为object,在使用 == 操作符时,JavaScript 会尝试各种求值,以检测两者是否会在某种情况下相等。所以下面的表达式结果为 true: strA == strB。

2、第二种操作符是”严格”的 ===,它在求值时不会这么宽容,不会进行类型转换。所以表达式 strA === strB 的值为false,虽然两个变量持有的值相同。
有时代码的逻辑要求你判断两个值是否不相等,这里也有两个选择:”!=”和严格的”!==”,它们的关系就类似于”==”和”===”。

“==”和”!=”在求值时会尽可能地寻找值的匹配性,但你可能还是想在比较前进行显式的类型转换,以”帮助”它们完成工作。比如,如果想判断一个用户的输入值(字符串)是否等于一个数字,你可以让”==”帮你完成类型转换:

if(document.form1.txtAge.value == someNumericVar) {
   …
}

也可以提前转换:

if(parseInt(document.form1.txtAge.value) == someNumericVar) {
  …
}

字符串大小比较

javascript 字符串在进行大于(小于)比较时,会根据第一个不同的字符的 ascii 值码进行比较。
当数字(number)与字符串(string)进行比较大小时,JavaScript 会首先将其转化为数字(number)再判定大小。

var numbers = ['APP_20221219', 'APP_20221221', 'APP_20221227'];
numbers.forEach((item, index) => {
    if (item < 'APP_20221224') {
        console.log(item)
    }
});

结果
APP_20221219
APP_20221221


substring()

substring() 方法返回一个字符串在开始索引到结束索引之间的一个子集, 或从开始索引直到字符串的末尾的一个子集。
str.substring(indexStart[, indexEnd])
indexStart 需要截取的第一个字符的索引,该索引位置的字符作为返回的字符串的首字母。
indexEnd 可选。一个 0 到字符串长度之间的整数,以该数字为索引的字符不包含在截取的字符串内。


slice() 字符串切片

slice(start, end) 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
参数:
start 必须。 要抽取的片断的起始下标,第一个字符位置为 0。如果为负数,则从尾部开始截取。
end 可选。 紧接着要截取的片段结尾的下标。若未指定此参数,则要提取的子串包括 start 到原字符串结尾的字符串。如果该参数是负数,那么它规定的是从字符串的尾部开始算起的位置。

slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。


startsWith() 以开头

startsWith() 方法用来判断当前字符串是否以另外一个给定的子字符串开头,并根据判断结果返回 true 或 false。

const str1 = 'Saturday night plans';

console.log(str1.startsWith('Sat'));
// expected output: true

console.log(str1.startsWith('Sat', 3));
// expected output: false

String.prototype.startsWith()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith


includes() 是否包含子串

includes() 方法用于判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false。
includes() 方法是区分大小写的。

var string = "foo", substring = "oo";
console.log(string.includes(substring));

String.prototype.includes()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/includes


atob() base64 解码

var b64s = ['dGhpcyBpcyBtYXNpa2tr', 'dGhpcyBpcyBkZGRkZA=='];
b64s.forEach((item, index) => {console.log(atob(item))});

How can you encode a string to Base64 in JavaScript?
https://stackoverflow.com/questions/246801/how-can-you-encode-a-string-to-base64-in-javascript


数组

forEach() 遍历

Array.prototype.forEach()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

forEach() 方法是一个迭代方法。它按索引升序地为数组中的每个元素调用一次提供的 callbackFn 函数。

语法:

forEach(callbackFn)
forEach(callbackFn, thisArg)

参数:
callbackFn 是为数组中每个元素执行的函数:

  • element 必需,数组中正在处理的当前元素。
  • index 可选,数组中正在处理的当前元素的索引。
  • array 可选,调用了 forEach() 的数组本身。

thisArg 可选。执行 callbackFn 时用作 this 的值。如果这个参数为空, “undefined” 会传递给 “this” 值。
最终由 callbackFn 观察到的 this 值根据通常的规则 确定:如果 callbackFn 是非严格模式(译注:正常模式/马虎模式),原始 this 值将被包装为对象,并将 undefined/null 替换为 globalThis。对于使用 箭头函数 定义的任何 callbackFn 来说,thisArg 参数都是无关紧要的,因为箭头函数没有自己的 this 绑定。

语法形式

// 箭头函数
forEach((element) => { /* … */ })
forEach((element, index) => { /* … */ })
forEach((element, index, array) => { /* … */ })

// 回调函数
forEach(callbackFn)
forEach(callbackFn, thisArg)

// 内联回调函数
forEach(function(element) { /* … */ })
forEach(function(element, index) { /* … */ })
forEach(function(element, index, array){ /* … */ })
forEach(function(element, index, array) { /* … */ }, thisArg)

例1,forEach 遍历数组对象

var numbers = ['hello', 'my', 'world'];
numbers.forEach((item, index) => {console.log(item)});

map()

Array.prototype.map()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map

map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

例如:

function pow(x) {
    return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
console.log(results);
var array1 = [1, 4, 9, 16];

// pass a function to map
const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]

对 b64s 做流式处理:

var b64s = ['app1@dGFibGUxL3RoaXMgaXMgbWFzaWtraw==', 'app2@dGFibGUyL3RoaXMgaXMgZGRkZGQ='];
b64s
    .map((item, index) => {
        return item.substring(item.indexOf('@') + 1)
     })
    .map((item, index) => {
        return atob(item);
     })
    .forEach((item, index) => {
        var tabname = item.substring(0, item.indexOf('/'));
        var str = item.substring(item.indexOf('/')+1);
    console.log(tabname, str);
     });

reduce()

Array.prototype.reduce()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

reduce() 方法对数组中的每个元素执行一个传入的 reducer 函数(升序执行),将其结果汇总为单个返回值。

语法:

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

callback 执行数组中每个值的函数,包含四个参数:

  • accumulator 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。
  • currentValue 数组中正在处理的元素。
  • currentIndex 可选 数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则为1。
  • array 可选 调用reduce()的数组

initialValue 可选 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。
返回值 函数累计处理的结果

回调函数第一次执行时,accumulator 和 currentValue 的取值有两种情况:如果调用 reduce() 时提供了 initialValue,accumulator 取值为 initialValue,currentValue 取数组中的第一个值;如果没有提供 initialValue,那么 accumulator 取数组中的第一个值,currentValue 取数组中的第二个值。

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

例如

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15

js求集合并集交集差集

a = [1, 2, 3];
b = [2, 4, 5];

// 并集
let union = a.concat(b.filter(v => !a.includes(v))) // [1,2,3,4,5]
console.log(union)

// 交集
let intersection = a.filter(v => b.includes(v)) // [2]
console.log(intersection)

// 差集
let difference = a.concat(b).filter(v => !a.includes(v) || !b.includes(v)) // [1,3,4,5]
console.log(difference)

js数组元素去重

a = [1,2,2,3,4];

b = Array.from(new Set(a));
console.log(b);

js数组判空

var arr = [];
if(Array.isArray(arr) && arr.length === 0){
    console.log('是空数组');
}

布尔值

js 中 ! 用于 bool 值取反

!true   // → false
!false  // → true
!"abc"  // → false(非空字符串为真,取反后为假)
!null   // → true(null 为假,取反后为真)
!0      // → true(0 为假,取反后为真)

!! 将一个值强制转换为布尔值(true 或 false)的技巧:

!!null        // → false(没有 token)
!!undefined   // → false(没有 token)
!!""          // → false(空 token)
!!"abc123"    // → true(有效 token)
!!0           // → false(异常数值)

对象

判断对象是否包含某个key

1、in 运算法
如果指定的属性在指定的对象或父类中,则in 运算符返回true

if ( !'WebSocket' in window) {
}

2、hasOwnProperty
返回一个布尔值,指示对象自身属性是否有指定的属性
和in不同,会忽略继承到的属性
即使属性的值是null,undefined,只要属性存在,hasOwnProperty依旧会返回true

if (!window.hasOwnProperty("WebSocket")) {
}
if (!window.WebSocket) {
}

图片

图片file转base64

const fileToBase64 = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
};

fileToBase64(file).then((base64) => {
  console.log(base64);
});

Math 对象

random() 0-1间的随机数

Math.random() 返回介于 0(包含) ~ 1(不包含) 之间的一个随机数:


Number 对象

toString() 转化为字符串

number.toString(radix)
radix 可选。规定表示数字的基数,是 2 ~ 36 之间的整数。若省略该参数,则使用基数 10。
但是要注意,如果该参数是 10 以外的其他值,则 ECMAScript 标准允许实现返回任意值。
2 - 数字以二进制值显示
8 - 数字以八进制值显示
16 - 数字以十六进制值显示
36 - 基数 36 表示使用数字 0-9 和字母 a-z 来表示数字。


全局函数

encodeURIComponent()

可把字符串作为 URI 组件进行编码
该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。

JSON.stringify() JSON序列化

将 JavaScript 值转换为 JSON 字符串

例如将一个 js 对象转为 json 串:

var person={firstname:"John", lastname:"Doe", id:5566};
console.log(JSON.stringify(person));

例如使用 Ajax 发送请求时,用 JSON.stringify() 将 变量 转为 json 串

var req = {"name":"name", "site":"http://www.masikkk.com"}
data: JSON.stringify(req)

JSON.parse() JSON反序列化

将一个 JSON 字符串转换为对象
JSON.parse(text[, reviver])
text:必需, 一个有效的 JSON 字符串。
reviver: 可选,一个转换结果的函数,将为对象的每个成员调用此函数。

const json = '{"result":true, "count":42}';
const obj = JSON.parse(json);

上一篇 JavaScript-异步

下一篇 TypeScript

阅读
评论
3.7k
阅读预计15分钟
创建日期 2025-08-24
修改日期 2025-08-24
类别

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论