2021.04.27(super 关键字、对象的扩展运算符)
作者:互联网
super 关键字
我们知道, this 关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键
字 super ,指向当前对象的原型对象。
1. const proto = { 2. foo: 'hello' 3. }; 4. 5. const obj = { 6. foo: 'world', 7. find() { 8. return super.foo; 9. } 10. }; 11. 12. Object.setPrototypeOf(obj, proto); 13. obj.find() // "hello"
上面代码中,对象 obj.find() 方法之中,通过 super.foo 引用了原型对象 proto 的 foo 属
性。
注意, super 关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。
1. // 报错 2. const obj = { 3. foo: super.foo 4. } 5. 6. // 报错 7. const obj = { 8. foo: () => super.foo 9. } 10. 11. // 报错 12. const obj = { 13. foo: function () { 14. return super.foo 15. } 16. }
上面三种 super 的用法都会报错,因为对于 JavaScript 引擎来说,这里的 super 都没有用在
对象的方法之中。第一种写法是 super 用在属性里面,第二种和第三种写法是 super 用在一个函
数里面,然后赋值给 foo 属性。目前,只有对象方法的简写法可以让 JavaScript 引擎确认,定
义的是对象的方法。
JavaScript 引擎内部, super.foo 等同于 Object.getPrototypeOf(this).foo (属性)
或 Object.getPrototypeOf(this).foo.call(this) (方法)。
1. const proto = { 2. x: 'hello', 3. foo() { 4. console.log(this.x); 5. }, 6. }; 7. 8. const obj = { 9. x: 'world', 10. foo() { 11. super.foo(); 12. } 13. } 14. 15. Object.setPrototypeOf(obj, proto); 16. 17. obj.foo() // "world"
上面代码中, super.foo 指向原型对象 proto 的 foo 方法,但是绑定的 this 却还是当前对
象 obj ,因此输出的就是 world 。
对象的扩展运算符
《数组的扩展》一章中,已经介绍过扩展运算符( ... )。ES2018 将这个运算符引入了对象。
解构赋值
对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的(enumerable)、但尚
未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
1. let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; 2. x // 1 3. y // 2 4. z // { a: 3, b: 4 }
上面代码中,变量 z 是解构赋值所在的对象。它获取等号右边的所有尚未读取的键
( a 和 b ),将它们连同值一起拷贝过来。
由于解构赋值要求等号右边是一个对象,所以如果等号右边是 undefined 或 null ,就会报错,因
为它们无法转为对象。
1. let { ...z } = null; // 运行时错误 2. let { ...z } = undefined; // 运行时错误
解构赋值必须是最后一个参数,否则会报错。
1. let { ...x, y, z } = someObject; // 句法错误 2. let { x, ...y, ...z } = someObject; // 句法错误
上面代码中,解构赋值不是最后一个参数,所以会报错。
注意,解构赋值的拷贝是浅拷贝,即如果一个键的值是复合类型的值(数组、对象、函数)、那么解构
赋值拷贝的是这个值的引用,而不是这个值的副本。
1. let obj = { a: { b: 1 } }; 2. let { ...x } = obj; 3. obj.a.b = 2; 4. x.a.b // 2
上面代码中, x 是解构赋值所在的对象,拷贝了对象 obj 的 a 属性。 a 属性引用了一个对
象,修改这个对象的值,会影响到解构赋值对它的引用。
解构赋值的一个用处,是扩展某个函数的参数,引入其他操作。
1. function baseFunction({ a, b }) { 2. // ... 3. } 4. function wrapperFunction({ x, y, ...restConfig }) { 5. // 使用 x 和 y 参数进行操作 6. // 其余参数传给原始函数 7. return baseFunction(restConfig); 8. }
上面代码中,原始函数 baseFunction 接受 a 和 b 作为参数,函
数 wrapperFunction 在 baseFunction 的基础上进行了扩展,能够接受多余的参数,并且保留原
始函数的行为。
扩展运算符
对象的扩展运算符( ... )用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。
1. let z = { a: 3, b: 4 }; 2. let n = { ...z }; 3. n // { a: 3, b: 4 }
由于数组是特殊的对象,所以对象的扩展运算符也可以用于数组。
1. let foo = { ...['a', 'b', 'c'] }; 2. foo 3. // {0: "a", 1: "b", 2: "c"}
如果扩展运算符后面是一个空对象,则没有任何效果。
1. {...{}, a: 1} 2. // { a: 1 }
如果扩展运算符后面不是对象,则会自动将其转为对象。
1. // 等同于 {...Object(1)} 2. {...1} // {}
上面代码中,扩展运算符后面是整数 1 ,会自动转为数值的包装对象 Number{1} 。由于该对象没
有自身属性,所以返回一个空对象。
2021-04-27 15:41:34
标签:...,27,obj,2021.04,对象,解构,运算符,foo,super 来源: https://www.cnblogs.com/zhenggc99/p/14709256.html