6To5 编译器 - 使用 __proto__ 进行继承

6To5 Compiler - use __proto__ for inheritance

作为 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 proto 应该是对象,但在代码中用于设置函数

Can anybody describe what for used updating __proto__ property?

ES6 规范当 类 相互继承时,生成的构造函数也应该相互继承。 CoreController.isPrototypeOf(Controller) 将产生 true.

As i try - it doesn't nothing useful

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

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

documentation says that proto should be object, but in code is used for setting function

在JS中每个函数都是一个对象。有样机,可以当一机。

不是你问题的真正答案,而是关于覆盖继承的更多警告:

分配对象的 __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

The __proto__ is deadly for the type inference, basically, after doing that this means that Type Inference is unable to follow any of the properties of the object as you are changing the underlying object lookup behind his back.

This basically means that every lookup you do on this object or any object created with this constructor will fallback on a slow path for reading/writing properties to the object. I might under estimate this issue, Eric would know better. (ni: efaust)

比那更糟

当您设置 __proto__ 时,您不仅会毁掉任何可能的机会 Ion 对该对象进行了未来优化,但您 还迫使引擎爬行到所有其他部分 TI(有关函数 return 值或 属性 值的信息, 也许)认为他们知道这个对象并告诉他们不要 做出许多假设,这涉及进一步的去优化 并且可能会使现有的 jitcode 失效。

在执行过程中改变对象的原型是 真是一把讨厌的大锤,也是我们必须避免的唯一方法 犯错是为了安全起见,但安全是缓慢的。如果可能,请尝试 直接用你想要的原型链创建。如果我们真的不得不 动态地调配原型链,我不确定我有很好的 关于如何最小化其性能影响的建议 动作。

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

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 的类似问题中说:

Notice how ‘static’ properties are added after extension.

It’s deprecated because it doesn’t give the interpreter a way to know beforehand that the object (function, in this case) has a different prototype chain than the standard one. Every JS interpreter implements it, and that’s because there’s still no perfect agreement on Object.setPrototypeOf, in fact for performance reasons IMO.

And looks like that 6to5 wants to be as compatible as possible to ES6 semantics, so setting Child.proto to Parent is an acceptable tradeoff.

详细讨论可以在link找到:https://github.com/babel/babel/issues/87#issuecomment-60139066

此外,您可以查看 basarat 中关于变异 [[Prototype]] 和 link 性能的好问题: Why is mutating the [[prototype]] of an object bad for performance?