关于es6里,prototype与__proto__
发布于 9 年前 作者 hinson0 7900 次浏览 最后一次编辑是 8 年前 来自 问答
'use strict';

class A { 

}

class B extends A  {

}

console.log(B.__proto__ === A); // true  第1行
console.log(B.prototype.__proto__ === A.prototype); // true 第2行

console.log(A.__proto__ === Function.prototype); // true 第3行
console.log(A.prototype.__proto__ === Object.prototype); // true 第4行

疑问:【第3,4行】是es5的知识点,没啥疑问的。但【第1行】我始终不明白,为什么B.proto === A ??? 将B看作Function类的一个实例,那么B继承A,不应该也是等于A.prototype么 难道是es6中的extends关键字的效果么?

2 回复

是的,es6中的extends实现继承的关键代码如下:

    function _inherits(subClass, superClass) {
        if (typeof superClass !== 'function' && superClass !== null) {
            throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
        }
        subClass.prototype = Object.create(superClass && superClass.prototype, {
            constructor: {
                value: subClass,
                enumerable: false,
                writable: true,
                configurable: true
            }
        });
        if (superClass)
            Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; // 这里
    }

最后一行会使用ES6新特性的Object.setPrototypeOf或一则polyfill将subClass__proto__设置为superClassprototype,的确是es6中extends关键字效果。 一般来说,继承这样来做:

B继承A

    B.prototype = {
        constructor: B,
        __proto__: A.prototype
    }

但是这样做的问题是对OOP的模拟不彻底:A的“静态成员”B是无法“继承”下来的,所以有两种做法:

  • 使用mixin将A的"静态成员"混入B中,比如使用Object.assign简单复制下引用;
  • B.__proto__直接引用A.prototype,即Object.setPrototypeOf(B, A);

js仅仅是使用原型的引用传递来模拟OOP,如果非得通过B.__proto__ === Function.prototype就把B看作Function类的一个实例来思考是肯定行不通的

回到顶部