欢迎扫码,加作者微信

ES6-12入门到精通教程

2022-08-23 06:27:11
2025-11-12 20:01:17

let 与 const

代码块内有效

let 是在代码块内有效,var 是在全局范围内有效:

js 复制代码
{
  let a = 0;
  a   // 0
}
a   // 报错 ReferenceError: a is not defined

不能重复声明

let 只能声明一次 var 可以声明多次:

js 复制代码
let a = 1;
let a = 2;
var b = 3;
var b = 4;
a  // Identifier 'a' has already been declared
b  // 4

for 循环计数器很适合用 let

变量 i 是用 var 声明的,在全局范围内有效,所以全局中只有一个变量 i, 每次循环时,setTimeout 定时器里面的 i 指的是全局变量 i ,而循环里的十个 setTimeout 是在循环结束后才执行,所以此时的 i 都是 10。
变量 j 是用 let 声明的,当前的 j 只在本轮循环中有效,每次循环的 j 其实都是一个新的变量,所以 setTimeout 定时器里面的 j 其实是不同的变量,即最后输出 12345。(若每次循环的变量 j 都是重新声明的,如何知道前一个循环的值?这是因为 JavaScript 引擎内部会记住前一个循环的值)。

js 复制代码
for (var i = 0; i < 10; i++) {
  setTimeout(function(){
    console.log(i);
  })
}
// 输出十个 10
for (let j = 0; j < 10; j++) {
  setTimeout(function(){
    console.log(j);
  })
}
// 输出 0123456789

不存在变量提升

let 不存在变量提升,var 会变量提升:
变量 b 用 var 声明存在变量提升,所以当脚本开始运行的时候,b 已经存在了,但是还没有赋值,所以会输出 undefined。
变量 a 用 let 声明不存在变量提升,在声明变量 a 之前,a 不存在,所以会报错。

js 复制代码
console.log(a);  //ReferenceError: a is not defined
let a = "apple";
 
console.log(b);  //undefined
var b = "banana";

const 声明一个只读的常量,一旦声明,常量的值就不能改变。

const 声明一个只读变量,声明之后不允许改变。意味着,一旦声明必须初始化,否则会报错。

language 复制代码
const PI = "3.1415926";
PI  // 3.1415926

const MY_AGE;  // SyntaxError: Missing initializer in const declaration    

暂时性死区:

ES6 明确规定,代码块内如果存在 let 或者 const,代码块会对这些命令声明的变量从块的开始就形成一个封闭作用域。代码块内,在声明变量 PI 之前使用它会报错。

js 复制代码
var PI = "a";
if(true){
  console.log(PI);  // ReferenceError: PI is not defined
  const PI = "3.1415926";
}

注意要点

const 如何做到变量在声明初始化之后不允许改变的?其实 const 其实保证的不是变量的值不变,而是保证变量指向的内存地址所保存的数据不允许改动。此时,你可能已经想到,简单类型和复合类型保存值的方式是不同的。是的,对于简单类型(数值 number、字符串 string 、布尔值 boolean),值就保存在变量指向的那个内存地址,因此 const 声明的简单类型变量等同于常量。而复杂类型(对象 object,数组 array,函数 function),变量指向的内存地址其实是保存了一个指向实际数据的指针,所以 const 只能保证指针是固定的,至于指针指向的数据结构变不变就无法控制了,所以使用 const 声明复杂类型对象时要慎重。

解构赋值

解构的源,解构赋值表达式的右边部分。
解构的目标,解构赋值表达式的左边部分

数组模型的解构(Array)

基本

js 复制代码
let [a, b, c] = [1, 2, 3];
// a = 1
// b = 2
// c = 3

可嵌套

js 复制代码
let [a, [[b], c]] = [1, [[2], 3]];
// a = 1
// b = 2
// c = 3

可忽略

js 复制代码
let [a, , b] = [1, 2, 3];
// a = 1
// b = 3

不完全解构

js 复制代码
let [a = 1, b] = []; // a = 1, b = undefined

剩余运算符

js 复制代码
let [a, ...b] = [1, 2, 3];
//a = 1
//b = [2, 3]

字符串等

在数组的解构中,解构的目标若为可遍历对象,皆可进行解构赋值。可遍历对象即实现 Iterator 接口的数据。

js 复制代码
let [a, b, c, d, e] = 'hello';
// a = 'h'
// b = 'e'
// c = 'l'
// d = 'l'
// e = 'o'

解构默认值

js 复制代码
let [a = 2] = [undefined]; // a = 2

当解构模式有匹配结果,且匹配结果是 undefined 时,会触发默认值作为返回结果。

js 复制代码
let [a = 3, b = a] = [];     // a = 3, b = 3
let [a = 3, b = a] = [1];    // a = 1, b = 1
let [a = 3, b = a] = [1, 2]; // a = 1, b = 2
  • a 与 b 匹配结果为 undefined ,触发默认值:a = 3; b = a =3
  • a 正常解构赋值,匹配结果:a = 1,b 匹配结果 undefined ,触发默认值:b = a =1
  • a 与 b 正常解构赋值,匹配结果:a = 1,b = 2

对象模型的解构(Object)

基本

js 复制代码
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
// foo = 'aaa'
// bar = 'bbb'
 
let { baz : foo } = { baz : 'ddd' };
// foo = 'ddd'

可嵌套可忽略

js 复制代码
let obj = {p: ['hello', {y: 'world'}] };
let {p: [x, { y }] } = obj;
// x = 'hello'
// y = 'world'
let obj = {p: ['hello', {y: 'world'}] };
let {p: [x, {  }] } = obj;
// x = 'hello'

不完全解构

js 复制代码
let obj = {p: [{y: 'world'}] };
let {p: [{ y }, x ] } = obj;
// x = undefined
// y = 'world'

剩余运算符

js 复制代码
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40};
// a = 10
// b = 20
// rest = {c: 30, d: 40}

解构默认值

js 复制代码
let {a = 10, b = 5} = {a: 3};
// a = 3; b = 5;
let {a: aa = 10, b: bb = 5} = {a: 3};
// aa = 3; bb = 5;

字符串

  • includes():返回布尔值,判断是否找到参数字符串。
  • startsWith():返回布尔值,判断参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,判断参数字符串是否在原字符串的尾部。

以上三个方法都可以接受两个参数,需要搜索的字符串,和可选的搜索起始位置索引。

js 复制代码
let string = "apple,banana,orange";
string.includes("banana");     // true
string.startsWith("apple");    // true
string.endsWith("apple");      // false
string.startsWith("banana",6)  // true

注意点:这三个方法只返回布尔值,如果需要知道子串的位置,还是得用 indexOf 和 lastIndexOf 。
这三个方法如果传入了正则表达式而不是字符串,会抛出错误。而 indexOf 和 lastIndexOf 这两个方法,它们会将正则表达式转换为字符串并搜索它。

字符串重复

repeat():返回新的字符串,表示将字符串重复指定次数返回。
js 复制代码
console.log("Hello,".repeat(2));  // "Hello,Hello,"
如果参数是小数,向下取整
js 复制代码
console.log("Hello,".repeat(3.2));  // "Hello,Hello,Hello,"
如果参数是 0 至 -1 之间的小数,会进行取整运算,0 至 -1 之间的小数取整得到 -0 ,等同于 repeat 零次
js 复制代码
console.log("Hello,".repeat(-0.5));  // "" 
如果参数是 NaN,等同于 repeat 零次
js 复制代码
console.log("Hello,".repeat(NaN));  // "" 
如果参数是负数或者 Infinity ,会报错:
js 复制代码
console.log("Hello,".repeat(-1));  
// RangeError: Invalid count value

console.log("Hello,".repeat(Infinity));  
// RangeError: Invalid count value
如果传入的参数是字符串,则会先将字符串转化为数字
js 复制代码
console.log("Hello,".repeat("hh")); // ""
console.log("Hello,".repeat("2"));  // "Hello,Hello,"
字符串补全
  • padStart:返回新的字符串,表示用参数字符串从头部(左侧)补全原字符串。
  • padEnd:返回新的字符串,表示用参数字符串从尾部(右侧)补全原字符串。

以上两个方法接受两个参数,第一个参数是指定生成的字符串的最小长度,第二个参数是用来补全的字符串。如果没有指定第二个参数,默认用空格填充。

js 复制代码
console.log("h".padStart(5,"o"));  // "ooooh"
console.log("h".padEnd(5,"o"));    // "hoooo"
console.log("h".padStart(5));      // "    h"

ES6+ 中常用的数组方法

1. forEach()

遍历数组,对每个元素执行回调函数

javascript 复制代码
const numbers = [1, 2, 3, 4];
numbers.forEach((item, index, array) => {
    console.log(`索引 ${index}: ${item}`);
});
// 输出:
// 索引 0: 1
// 索引 1: 2
// 索引 2: 3
// 索引 3: 4

2. map()

创建新数组,包含原数组每个元素调用函数后的结果

javascript 复制代码
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6]

const users = [
    { name: 'Alice', age: 25 },
    { name: 'Bob', age: 30 }
];
const names = users.map(user => user.name);
console.log(names); // ['Alice', 'Bob']

3. filter()

创建新数组,包含所有通过测试的元素

javascript 复制代码
const numbers = [1, 2, 3, 4, 5, 6];
const even = numbers.filter(num => num % 2 === 0);
console.log(even); // [2, 4, 6]

const products = [
    { name: '手机', inStock: true },
    { name: '电脑', inStock: false },
    { name: '平板', inStock: true }
];
const availableProducts = products.filter(product => product.inStock);
console.log(availableProducts); // [{name: '手机', inStock: true}, {name: '平板', inStock: true}]

4. find() & findIndex()

查找第一个满足条件的元素/索引

javascript 复制代码
const users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
    { id: 3, name: 'Charlie' }
];

const user = users.find(user => user.id === 2);
console.log(user); // {id: 2, name: 'Bob'}

const index = users.findIndex(user => user.name === 'Charlie');
console.log(index); // 2

5. some() & every()

检查数组中是否至少有一个/所有元素满足条件

javascript 复制代码
const numbers = [1, 2, 3, 4, 5];

const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // true

const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // true

6. reduce() & reduceRight()

将数组缩减为单个值(从左到右/从右到左)

javascript 复制代码
const numbers = [1, 2, 3, 4, 5];

// 求和
const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum); // 15

// 分组
const people = [
    { name: 'Alice', age: 25 },
    { name: 'Bob', age: 30 },
    { name: 'Charlie', age: 25 }
];

const groupedByAge = people.reduce((groups, person) => {
    const age = person.age;
    if (!groups[age]) {
        groups[age] = [];
    }
    groups[age].push(person);
    return groups;
}, {});

console.log(groupedByAge);
// {25: [{name: 'Alice', age: 25}, {name: 'Charlie', age: 25}], 30: [{name: 'Bob', age: 30}]}

7. flat() & flatMap()

扁平化数组

javascript 复制代码
// flat()
const nested = [1, 2, [3, 4, [5, 6]]];
console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]]
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]

// flatMap()
const sentences = ["Hello world", "Good morning"];
const words = sentences.flatMap(sentence => sentence.split(' '));
console.log(words); // ["Hello", "world", "Good", "morning"]

8. includes()

检查数组是否包含某个元素

javascript 复制代码
const fruits = ['apple', 'banana', 'orange'];
console.log(fruits.includes('banana')); // true
console.log(fruits.includes('grape')); // false

9. Array.from()

从类数组或可迭代对象创建新数组

javascript 复制代码
// 从字符串
const fromString = Array.from('hello');
console.log(fromString); // ['h', 'e', 'l', 'l', 'o']

// 从Set
const fromSet = Array.from(new Set([1, 2, 2, 3, 3]));
console.log(fromSet); // [1, 2, 3]

// 带映射函数
const squares = Array.from([1, 2, 3], x => x * x);
console.log(squares); // [1, 4, 9]

10. Array.of()

根据参数创建新数组

javascript 复制代码
const numbers = Array.of(1, 2, 3, 4);
console.log(numbers); // [1, 2, 3, 4]

// 与 Array 构造函数的区别
console.log(Array(3)); // [empty × 3]
console.log(Array.of(3)); // [3]

11. fill()

用固定值填充数组

javascript 复制代码
const arr = new Array(5).fill(0);
console.log(arr); // [0, 0, 0, 0, 0]

const numbers = [1, 2, 3, 4, 5];
numbers.fill('*', 1, 3);
console.log(numbers); // [1, '*', '*', 4, 5]

12. copyWithin()

在数组内部复制元素序列

javascript 复制代码
const numbers = [1, 2, 3, 4, 5];
numbers.copyWithin(0, 3);
console.log(numbers); // [4, 5, 3, 4, 5]

13. entries(), keys(), values()

返回数组的迭代器对象

javascript 复制代码
const fruits = ['apple', 'banana', 'orange'];

// entries() - 键值对
for (const [index, fruit] of fruits.entries()) {
    console.log(index, fruit);
}

// keys() - 键
for (const key of fruits.keys()) {
    console.log(key); // 0, 1, 2
}

// values() - 值
for (const value of fruits.values()) {
    console.log(value); // 'apple', 'banana', 'orange'
}

实际应用示例

javascript 复制代码
// 数据处理管道
const data = [
    { name: 'Alice', age: 25, salary: 50000, department: 'IT' },
    { name: 'Bob', age: 30, salary: 60000, department: 'HR' },
    { name: 'Charlie', age: 35, salary: 70000, department: 'IT' },
    { name: 'David', age: 28, salary: 55000, department: 'Finance' }
];

// 计算IT部门员工的平均薪资
const itAvgSalary = data
    .filter(employee => employee.department === 'IT')
    .map(employee => employee.salary)
    .reduce((sum, salary, index, array) => {
        sum += salary;
        if (index === array.length - 1) {
            return sum / array.length;
        }
        return sum;
    }, 0);

console.log(`IT部门平均薪资: ${itAvgSalary}`); // IT部门平均薪资: 60000

在 ES6 中,有以下数组方法会直接影响原数组

会改变原数组的 ES6 方法:

1. copyWithin()

javascript 复制代码
const arr = [1, 2, 3, 4, 5];
arr.copyWithin(0, 3); // 将索引3开始的元素复制到索引0
console.log(arr); // [4, 5, 3, 4, 5]

2. fill()

javascript 复制代码
const arr = [1, 2, 3, 4, 5];
arr.fill(0, 1, 3); // 将索引1-3的元素填充为0
console.log(arr); // [1, 0, 0, 4, 5]

传统方法(ES5及之前,但ES6中仍然存在):

3. push() / pop()

javascript 复制代码
const arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4]
arr.pop();   // [1, 2, 3]

4. shift() / unshift()

javascript 复制代码
const arr = [1, 2, 3];
arr.shift();   // [2, 3]
arr.unshift(0); // [0, 2, 3]

5. splice()

javascript 复制代码
const arr = [1, 2, 3, 4, 5];
arr.splice(1, 2, 'a', 'b'); // 从索引1删除2个元素,并插入新元素
console.log(arr); // [1, 'a', 'b', 4, 5]

6. reverse()

javascript 复制代码
const arr = [1, 2, 3];
arr.reverse(); // [3, 2, 1]

7. sort()

javascript 复制代码
const arr = [3, 1, 2];
arr.sort(); // [1, 2, 3]

不会改变原数组的方法:

以下方法会返回新数组,不会改变原数组

  • map()
  • filter()
  • slice()
  • concat()
  • flat()
  • flatMap()
javascript 复制代码
const arr = [1, 2, 3];
const newArr = arr.map(x => x * 2);
console.log(arr);    // [1, 2, 3] - 原数组不变
console.log(newArr); // [2, 4, 6] - 新数组

总结:在 ES6 新增方法中,只有 copyWithin()fill() 会直接修改原数组。

文章目录

生成中...

扫码赞赏

感谢您的支持与鼓励

安全支付

支付赞赏

您的支持是我们前进的动力

留言
快捷金额
自定义金额
¥

安全保障

采用银行级加密技术,保障您的支付安全

暂无评论,欢迎留下你的评论

暂无评论

期待您的精彩留言!
成为第一个评论的人吧 ✨

写下第一条评论
Copyright © 2025 粤ICP备19043740号-1
🎉 今日第 1 位访客 📊 年访问量 0 💝 累计赞赏 1000+