6To5编译器 - 使用__proto__继承

时间:2015-02-23 12:57:48

标签: prototype ecmascript-6 porting ecmascript-5

作为6to5的输出,我得到了以下代码:

var _inherits = function (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
      }
    });
    // question is about next row
    if (superClass) subClass.__proto__ = superClass;
  };
_inherits(Controller, CoreController);

有人可以描述使用更新__proto__属性的内容吗?正如我尝试的那样 - 它并没有什么用处

P.S。 as documentation says原型应该是对象,但在代码中用于设置功能

3 个答案:

答案 0 :(得分:3)

  

有人可以描述使用更新__proto__属性的内容吗?

ES6规范当类继承彼此时,结果构造函数也应该相互继承。 CoreController.isPrototypeOf(Controller)会产生true

  

正如我尝试的那样 - 它并没有什么用处

它对于继承静态属性非常有用,静态属性放在JS中的构造函数中。

CoreController.hi = console.log.bind(console, "hello world");
CoreController.hi(); // hello world
Controller.hi(); // error
_inherits(Controller, CoreController);
Controller.hi(); // hello world
  

文档说原型应该是对象,但在代码中用于设置功能

每个函数都是JS中的一个对象。它有一个原型,它可以作为一个原型。

答案 1 :(得分:2)

不是你的问题的答案,而是关于重写继承的更多警告:

分配对象的__proto__属性或使用等效的ES6 Object.setPrototypeOf()会对此类对象触及的任何代码路径产生严重的性能影响。

Blog post with benchmarks显示了一些性能影响。

Firefox执行此操作时会发出警告:

mutating the [[Prototype]] of an object will cause your code to run very slowly;
instead create the object with the correct initial [[Prototype]] value using Object.create 

引用mozilla bug 984146

  
    

__proto__对于类型推断是致命的,基本上,在这样做之后     这意味着类型推断无法遵循任何属性     当你正在改变他背后的底层对象时,该对象。

         

这基本上意味着您对此对象或任何对象执行的每次查找     使用此构造函数创建的将在慢速路径上回退     读/写对象的属性。我可能估计这个     问题,埃里克会更清楚。 (ni:efaust)

  
     

甚至比那更糟。

     

当你设置__proto__时,你不仅会破坏任何机会   已经有了Ion对该对象的未来优化,但是你   也迫使发动机爬到所有其他部分   TI(有关函数返回值或属性值的信息,   也许)认为他们知道这个对象,并告诉他们不要   做出许多假设,这涉及进一步的去优化   并且可能使现有的jitcode无效。

     

在执行过程中更改对象的原型是   真的是一个讨厌的大锤,也是我们必须避开的唯一方法   错误是安全,但安全慢。如果可能,尝试   直接使用您想要的原型链创建。如果我们真的需要   动态的swizzle原型链,我不确定我有多好   关于如何最小化其性能影响的建议   动作。

答案 2 :(得分:2)

它用于'静态'属性继承。请参阅下面的代码示例:

class Parent {
 myMethod() {}
}

console.log(Parent.prototype.myMethod); // [Function]
console.log(Parent.prototype.hasOwnProperty('myMethod')); // true
console.log(Parent.myMethod); // undefined

class Child extends Parent {}

console.log(Child.prototype.myMethod); // Function
console.log(Child.prototype.hasOwnProperty('myMethod')); // false
console.log(Child.myMethod); // undefined

Parent.myStaticProp = 42;

console.log(Parent.prototype.myStaticProp); // undefined
console.log(Parent.myStaticProp); // 42
console.log(Parent.hasOwnProperty('myStaticProp')); // true

console.log(Child.prototype.myStaticProp); // undefined
console.log(Child.myStaticProp); // 42
console.log(Child.hasOwnProperty('myStaticProp')); // false

此外,在github的类似问题中,yuchi说:

  

注意扩展后如何添加“静态”属性。

     

它已被弃用,因为它不会让解释器知道   事先确定对象(在这种情况下,功能)有不同   原型链比标准链。每个JS解释器都实现   它,那是因为仍然没有完美的协议   Object.setPrototypeOf,实际上是出于性能原因IMO。

     

看起来6to5希望尽可能与ES6兼容   语义,所以将Child。 proto 设置为Parent是可以接受的   折衷。

您可以通过以下链接找到详细讨论:https://github.com/babel/babel/issues/87#issuecomment-60139066

另外,您可以通过以下链接查看basarat关于突变[[Prototype]]和性能的好问题: Why is mutating the [[prototype]] of an object bad for performance?