Javascript:覆盖函数的原型 - 糟糕的做法?

时间:2012-09-04 09:21:20

标签: javascript constructor prototype

因为当我们声明一个函数时,我们得到它的原型的构造函数属性指向函数本身,如此覆盖函数的原型是不好的做法:

function LolCat() {
}

// at this point LolCat.prototype.constructor === LolCat

LolCat.prototype = {
    hello: function () {
        alert('meow!');
    }
    // other method declarations go here as well
};

// But now LolCat.prototype.constructor no longer points to LolCat function itself

var cat = new LolCat();

cat.hello(); // alerts 'meow!', as expected

cat instanceof LolCat // returns true, as expected

我不是这样做的,我还是更喜欢以下方法

LolCat.prototype.hello = function () { ... }

但我经常看到其他人这样做。

因为为了方便起见,通过覆盖函数的原型对象,从原型中删除构造函数引用是否有任何影响或缺点?

6 个答案:

答案 0 :(得分:20)

就这一点而言,我看不到有人提到最佳实践,所以我认为这取决于你是否能看到constructor属性一直有用。

值得注意的是,constructor属性(如果不销毁它)也将在创建的对象上可用。在我看来,这可能是有用的:

var ClassOne = function() {alert("created one");}
var ClassTwo = function() {alert("created two");}

ClassOne.prototype.aProperty = "hello world"; // preserve constructor
ClassTwo.prototype = {aProperty: "hello world"}; // destroy constructor

var objectOne = new ClassOne(); // alerts "created one"
var objectTwo = new ClassTwo(); // alerts "created two"

objectOne.constructor(); // alerts "created one" again
objectTwo.constructor(); // creates and returns an empty object instance

所以在我看来,这是一个架构决策。是否允许创建的对象在实例化后重新调用其构造函数?如果这样保留它。如果没有,请将其销毁。

请注意,objectTwo的构造函数现在完全等于标准的Object构造函数 - 无用。

objectTwo.constructor === Object; // true

因此,调用new objectTwo.constructor()相当于new Object()

答案 1 :(得分:5)

这不是坏习惯,但你必须知道你在做什么以及为什么。它对原型继承非常有用。您覆盖原型的对象将获得您为其分配的对象的所有属性的原型:

您使用

导致对象继承
ChildClassName.prototype = new ParentClass();.

现在,ChildClassName具有ParentClass的所有功能,但丢失之前分配给它的原型的任何功能。您需要记住使用

重置对象的构造函数属性
ChildClassName.prototype.constructor=ChildClassName. 

否则将报告对象是(在测试对象类型时)ParentClass类型而不是ChildClassName类型。

现在,您可以按照自己描述的方式向ChildClassName对象添加更多方法。

ChildClassName.prototype.myMethod = function(){
    //do stuff
}

结果是父对象/'类(当然在javascript中没有真正的类)和子对象/'类'继承自它并扩展其功能。

您只需要知道,如果您覆盖原型,那么分配给它的任何属性都将消失。构建继承对象时,这可能正是您想要的。

答案 2 :(得分:3)

此表格:

LolCat.prototype = {
  hello: function () {
      alert('meow!');
  }
};

销毁任何现有方法和公共属性。在示例中,作为给定的,它并不重要,因为新创建的LolCat没有任何属性或方法。但是,在更复杂的代码中应该注意这一点。

此表格:

LolCat.prototype.hello = function () { ... }

向现有对象添加新方法并保持现有对象不变。

答案 3 :(得分:1)

使用原型继承时覆盖constructor并不是一种坏习惯。事实上很多人这样做:

LolCat.prototype = {
    constructor: LolCat,
    hello: function () {
        alert('meow!');
    }
};

答案 4 :(得分:0)

这不是一个坏习惯。但是有一种简单而标准的覆盖函数的方法,如下所示。当我们全局定义'函数LolCat()'时,它会在窗口下创建,因此您可以像下面一样编写代码。

window.LolCat = function() {...};
LolCat.prototype.hello = function () { ... }

答案 5 :(得分:0)

经过多年的javascript编写,我偶然发现了一个奇怪的错误:一个对象的新实例,然后用一个声明了__proto__类的时候,传递给mixin的prototype就失去了: >

MyClass.prototype = {
   constructor: MyClass,
   myMethod(){ ...}
};

使用时不再有问题:

Object.assign( MyClass.prototype, {
   myMethod(){ ...}
});

奖金:您不必重新分配结构。

我想这是因为当我们完全覆盖prototype属性时,我们也会擦除其特殊属性并将其转换为普通属性...也许默认情况下该属性不可写...