阮一峰ES6 笔记
本文最后更新于:2022年10月12日 上午
ECMAScript 6
Class的基本语法
类的实例
可以通过实例的__proto__属性为“类”添加方法,改写原型(不推荐使用,因为这会改变“类”的原始定义,影响到所有实例)
__proto__并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但依旧不建议在生产中使用该属性,避免对环境产生依赖。生产环境中,我们可以使用Object.getPrototypeOf方法来获取实例对象的原型,然后再来为原型添加方法/属性。
Class表达式
与函数一样,类也可以使用表达式的形式定义
| 1 |  | 
上面代码使用表达式定义了一个类。需要注意的是,这个类的名字是Me,但是Me只在 Class 的内部可用,指代当前类。在 Class 外部,这个类只能用MyClass引用。
| 1 |  | 
上面代码表示,Me只在 Class 内部有定义。
注意点
不存在提升
ES6 不会把类的声明提升到代码头部
| 1 |  | 
上面的代码不会报错,因为Bar继承Foo的时候,Foo已经有定义了。但是,如果存在class的提升,上面代码就会报错,因为class会被提升到代码头部,而let命令是不提升的,所以导致Bar继承Foo的时候,Foo还没有定义。
私有属性的提案
in 运算符
in运算符对于Object.create()、Object.setPrototypeOf形成的继承,是无效的,因为这种继承不会传递私有属性
new.target 属性
Class 内部调用new.target,返回当前 Class
子类继承父类时,new.target会返回子类
利用这个特点,可以写出不能独立使用、必须继承后才能使用的类
| 1 |  | 
上面代码中,Shape类不能被实例化,只能用于继承
class的继承
super关键字
第一种情况
super作为函数调用时,代表父类的构造函数,super()只能用在子类的构造函数之中
| 1 |  | 
上面代码中,子类B的构造函数之中的super(),代表调用父类的构造函数
注意,super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B的实例,因此super()在这里相当于A.prototype.constructor.call(this)
第二种情况
super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类
变量的解构赋值
对象的解构赋值
对象的解构赋值可以取到继承的属性
注意点
- 将一个已经声明的变量用于解构赋值时 - 错误写法: - 1 
 2
 3- let x;
 {x} = {x: 1};
 // SyntaxError: syntax error- JavaScript 引擎会将 - {x}理解成一个代码块- 解决方法:不将大括号写在行首,避免 JavaScript 将其解释为代码块 - 1 
 2- let x;
 ({x} = {x: 1});
- 数组本质是特殊的对象,因此可以对数组进行对象属性的解构 - 数组键值作为匹配模式 - 1 
 2
 3
 4- let arr = [1, 2, 3];
 let {0 : first, [arr.length - 1] : last} = arr;
 first // 1
 last // 3
用途
- 交换变量的值 - 1 
 2
 3
 4- let x = 1;
 let y = 2;
 [x, y] = [y, x];
- 从函数返回多个值 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- // 返回一个数组
 function example() {
 return [1, 2, 3];
 }
 let [a, b, c] = example();
 // 返回一个对象
 function example() {
 return {
 foo: 1,
 bar: 2
 };
 }
 let { foo, bar } = example();
- 函数参数的定义 - 1 
 2
 3
 4
 5
 6
 7- // 参数是一组有次序的值
 function f([x, y, z]) { ... }
 f([1, 2, 3]);
 // 参数是一组无次序的值
 function f({x, y, z}) { ... }
 f({z: 3, y: 2, x: 1});
- 提取 - JSON数据- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- let jsonData = {
 id: 42,
 status: "OK",
 data: [867, 5309]
 };
 let { id, status, data: number } = jsonData;
 console.log(id, status, number);
 // 42, "OK", [867, 5309]
- 函数参数的默认值 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- jQuery.ajax = function (url, {
 async = true,
 beforeSend = function () {},
 cache = true,
 complete = function () {},
 crossDomain = false,
 global = true,
 // ... more config
 } = {}) {
 // ... do stuff
 };
- 遍历 - Map结构- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21- const map = new Map();
 map.set('first', 'hello');
 map.set('second', 'world');
 for (let [key, value] of map) {
 console.log(key + " is " + value);
 }
 // first is hello
 // second is world
 //只想获取键名,或只想获取键值
 // 获取键名
 for (let [key] of map) {
 // ...
 }
 // 获取键值
 for (let [,value] of map) {
 // ...
 }
- 输入模块指定方法 - 1 - const { SourceMapConsumer, SourceNode } = require("source-map");