Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

ES6 的 super 到底是什么?

  说起 ES6 的继承和 super 的用法大家都不会陌生,可是一问到 super 到底是什么,很多人就支支吾吾。也许在别的编程语言中 super 和 this 一样,都是一个指针,可以像一般变量一样使用。但是在 ES6 中,super 是一个特殊的语法,而且它比 this 还要特殊,有很多用法上的限制。
  我们都知道,在使用 extends 关键字定义的 class 中,调用 constructor 里的 super 可以调用父类的构造器。这里就有两个问题。第一,既然 super 是一个可以调用的东西,它是一个函数么?第二,对于 extends 的 class,constructor 里可以没有 super 么?
  第一个问题的答案很容易找到,可以把 super 赋值到其它变量试试,会得到一个语法错误。
<script> class A extends Object { constructor() { const a = super; a(); } }; </script> Uncaught SyntaxError: 'super' keyword unexpected here   因为 super 的词法定义是伴随后面那对括号的,它和 this 不同。this 的定义是 this 这个关键字会被替换成一个引用,而 super 则是 super(...) 被替换成一个调用。而且 super 除了在 constructor 里直接调用外还可以使用 super.xxx(...) 来调用父类上的某个原型方法,这同样是一种限定语法。
<script> class A extends Array { push(...args) { args.forEach(item => super.push(item + 1)); } } let a = new A(); a.push(1, 2, 3); console.log(a); // [2, 3, 4] </script>   所以要是问 super 是什么,它只是一个关键字而已。用法应该是 super(...) 或者 super.xxx(...) 才对。
  第二个问题实际上是问 super(...) 到底做了什么。其实 super(...) 做的事情就是生成一个 this。因为在原型继承中,如果一个类要继承自另一个类,那就得先实例化一次它的父类作为作为子类的原型。如果不做这件事,子类的原型就不能确定,当然也就无法创建 this。所以如果在 constructor 中没有 super(...) 就企图获取 this 就会报错。 Uncaught ReferenceError: this is not defined   而且即使程序没有显式地访问 this,只要 constructor 没有提供一个对象作为构造结果就会导致外面的 new 去访问 constructor 的 this 造成上面这个错误被抛出。
<script> class A {} class B extends A { constructor() {} } new B(); // throw </script>   其实 constructor 中是可以没有 super(...) 的,它只不过是用来生成 this 的而已。如果只想继承原型,而根本不想管父类的构造器,可以完全避开 this,在 constructor 中手动返回一个对象,比如:
<script> class A { get one() { return 1; } } class B extends A { constructor() { return Object.create(new.target.prototype); } get two() { return 2; } }; let b = new B(); console.log(b.one, b.two); // 1 2 </script>
网名:
54.159.64.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^