其他分享
首页 > 其他分享> > 2021.04.27(super 关键字、对象的扩展运算符)

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