有没有有效的方法在javascript中使用`__proto__`或`setPrototypeOf()`?

时间:2017-09-29 00:38:49

标签: javascript inheritance prototype prototypal-inheritance prototype-chain

MDN对于修改代码中的原型有一个巨大的可怕警告:

  

根据具体情况,更改对象的-- evaluating `list` using definition of `list` list = 1 : tail list -- evaluating `tail list` using definition of `tail` list = 1 : case list of _:xs -> xs ... -- evaluating case construct requires matching `list` to -- a pattern, this requires evaluation of `list` using its defn list = 1 : case (1 : tail list) of _:xs -> xs ... -- case pattern match succeeds list = 1 : let xs = tail list in xs -- just to be clear = 1 : tail list -- awesome, now all we need to do is evaluate: list = 1 : tail list -- ummm, Houston, we have a problem   现代JavaScript引擎优化属性访问,非常慢   操作,在 每个 浏览器和JavaScript引擎中。对...的影响   改变遗传的表现是微妙而遥远的   不仅限于在[[Prototype]]声明中花费的时间,   但可以扩展到 任何 代码,该代码可以访问任何对象   Object.setPrototypeOf(...)已被更改。如果你关心你的表现   应该避免设置对象的[[Prototype]]。相反,创建一个   使用Object.create()的所需[[Prototype]]的新对象。

     

- MDN > JavaScript > Object.setPrototypeOf()

我想知道是否有任何情况下您可以修改对象的原型而不会导致级联优化效果,从而导致程序的性能下降。好像应该有。例如,如果您只是在创建对象之后(以及在其他任何东西使用之前)修改原型。但我想这是依赖引擎的。

所以有人知道是否有有效的方法来修改对象的原型?

编辑:此问题的动机来自于创建实际继承自[[Prototype]]的对象的愿望。我知道如何做到这一点的唯一方法是修改函数的原型。请参阅Raynos答案的最底部:javascript class inherit from Function class

2 个答案:

答案 0 :(得分:2)

  

这个问题的动机来自于创建实际上从Function继承的对象的愿望。

您正在尝试做的事情如下:

  • 创建对象
  • 设置这些对象'原型(或__proto__属性)引用Fuction.prototype以便它们从Function.prototype继承属性,例如:
    • .apply
    • .call
    • .bind

只要您可以在创建对象时将其正确设置为所需的引用,就不应该更改任何对象的原型。

答案一:如何设置对象的原型

您可以使用Object.create()在创建时设置任何对象的原型。请注意,将任何对象的原型分配给Function.prototype 会导致该对象成为可调用函数。但是,如果您仍想分配原型以引用Function.prototype或其他对象,则可以执行以下操作:

var obj1 = Object.create(Function.prototype);

这将:

  • 创建一个新对象obj1
  • 设置其原型(或__proto__属性)以引用Function.prototype或您传入的任何对象作为参数
    • 即,它会通过prototype chain将失败的属性查找委托给Function.prototype(这是JavaScript原型和__proto__引用的内容:委托失败的属性查找的地方)

not 要求您使用Object.setPrototypeOf()来更改现有对象的原型,因为它在创建对象时分配原型。有关更多示例和信息,请参阅Object.create()的MDN文档 - 这不会带有与setPrototypeOf()相同的可怕警告。您可以使用Object.create()设置任何新对象的原型。

答案二:功能已经是对象

也就是说,如果你想要一个行为类似于函数的对象,你可以简单地创建一个函数。函数仍然是一个对象,但具有其他特定于函数的属性和行为;您仍然可以通过为其指定属性来将其视为对象。如果您正在寻找创建一个也像对象一样的函数,或者一个也可以执行与函数相同的对象的函数,那么函数就已经这样做了。你可以这样做:

var func = function() { return 'hello world'; }; // func is a function
func.property1 = 'foo'; // func is also an object
func.property2 = 'bar';

你问题的最佳解决方案可能是利用这样一个事实,即功能实际上已经是具有附加功能的对象。

答案 1 :(得分:0)

当你想要一个像comportement这样的数组时,我知道改变原型只有一个原因。

    var class_func = { toto: function(){console.log('hi')}};
     ...
    var a = [];
    a.__proto__ = class_func 
    a.toto()
    //hi
    a[5] = 8
   // 8
    a.length
    //6

在这种情况下,最好直接在数组上添加函数。