是否可以分配JavaScript原型对象而不仅仅是其属性?

时间:2011-06-06 18:43:08

标签: javascript prototype-programming

在JavaScript中,我们可以为函数的原型指定属性或直接设置其原型对象:

var MyClass = function() { };

// The "property" form...
MyClass.prototype.foo = function() { ... };
MyClass.prototype.bar = function() { ... };
MyClass.prototype.gah = function() { ... };

// OR the "assignment" form...
MyClass.prototype = {
  foo:function() { ... },
  bar:function() { ... },
  gah:function() { ... }
};

我个人更喜欢分配表单,因为您可以轻松地将对象包装在一个闭包中(例如隐藏“私有”对象),如果您以后决定更改“MyClass”的名称,您只需要找到两个位置而不是潜在的几十个。 (当然,对于“属性”形式也可以这样说,通过使用和调用一个以现有原型作为参数的函数,但在我看来,“赋值”形式似乎更直接。)

是否有充分的理由使用一种形式而不是另一种形式?

[编辑]

正如评论者@Raynos所提到的,第二种形式(赋值)破坏了prototype.constructor属性,该属性应该设置为MyClass函数(默认情况下是第一种形式[property])。这有什么真正的缺点(除了没有设置属性的事实)?

4 个答案:

答案 0 :(得分:22)

不使用第二种形式的最大原因是,在分配原型之前,您最终会消除原型中存在的任何其他内容。如果那不是你所关心的事情,就没有理由不以你所展示的方式宣布它。

答案 1 :(得分:4)

我认为将“赋值”表单用于prototype属性还有另一个缺点:当你处理“伪”时,你可能会消灭prototype.__proto__属性(原型链) - 经典的“继承。

当然,人们可能会争辩说有一种方法可以解决这个问题,即自己附加__proto__属性以再次连接链。但是如果你调用父方法,忘记这样做会破坏代码。在这里看到我的小提琴:http://jsfiddle.net/glenn/v5Yub/

结论:“赋值”表单可能看起来更简单/更清晰,但“属性”表单更安全。

答案 2 :(得分:1)

我认为使用Object.assign分配函数原型而不破坏当前原型的最佳方法。

function myFunction() {

}

Object.assign(myFunction.prototype, {
    say(str) { return str },
    greet(name) { return "Hello " + name}
})

答案 3 :(得分:0)

自EcmaScript2015起,几乎没有理由再摆弄prototype属性了。

class语法提供了更直观的语法所需的内容:

class MyClass {
    constructor() { }
    foo() { ... }
    bar() { ... }
}

...以及需要更长的原型链时:

class MySuperClass {
    constructor() { }
    foo() { ... }
    bar() { ... }
}

class MyClass extends MySuperClass{
    constructor() { }
    gah() { ... }
}