实际使用javascript中的prototype.constructor

时间:2015-05-26 08:54:04

标签: javascript

简单来说,为什么我们使用prototype.constructor。我正在阅读一篇关于继承的文章,我看到prototype.constructor。当我评论该代码时,我发现结果没有区别。所以我的问题为何以及何时实际使用它。

function Mammal(name){ 
    this.name=name;
  this.action= function (){
  alert('0')
  }

} 



function Cat(name){ 
    this.name=name;
} 

Cat.prototype = new Mammal();

//Cat.prototype.constructor=Cat; // Otherwise instances of Cat would have a constructor of Mammal 



Cat.prototype.action=function(){
alert('1')
}

var y= new Mammal()
var x= new Cat()

y.action()

x.action()

1 个答案:

答案 0 :(得分:2)

这主要是惯例。虽然JavaScript本身没有使用constructor属性,但有时人们会在代码中使用它,假设它会引用回到对象的构造函数。这不仅仅是惯例,请参阅¹了解详细信息。

创建函数时:

function Cat() {
}

该函数从其prototype属性上的一个对象开始,该对象具有一个名为constructor的属性,该属性指向该函数:

console.log(Cat.prototype.constructor === Cat); // true

这是在规范中。 (这也是规范中提到属性的唯一位置 - 例如,JavaScript本身根本不使用此属性。不再是.¹)

因此,使用该原型创建的实例(无论是通过构造函数还是其他方式创建)都继承了constructor属性:

var c = new Cat();
console.log(c.constructor === Cat);  // true

var c2 = Object.create(Cat.prototype);
console.log(c2.constructor === Cat); // true, even though Cat wasn't used

替换函数上的prototype属性时,正如通常在构建层次结构时所做的那样:

Cat.prototype = new Mammal(); // This is an anti-pattern, btw, see below

...您最终得到Cat.prototype上的一个对象,其中constructor指向Mammal。由于这不是人们通常所期望的,所以习惯性地解决它:

Cat.prototype.constructor = Cat;

虽然JavaScript中没有任何内容使用属性(现在它已经¹),但有时人们会在代码中使用它,假设它会引用回对象的构造函数。

重新编写代码中的反模式:当使用构造函数构建层次结构时,实际上调用“基础”构造函数来创建“派生”构造函数{{1 }}。相反,使用prototype创建原型:

Object.create

...然后链接到Cat.prototype = Object.create(Mammal.prototype); Cat.prototype.constructor = Cat; 中的Mammal

Cat

为什么这样?考虑一下:如果基础需要参数,那么在构造时才能有意义地初始化实例会怎样?在拥有它们之前,你不能传递它。上面的模式允许您处理这种情况。

请注意,ES5中添加了function Cat() { Mammal.call(this); // ... } ,因此某些旧浏览器(如IE8)缺少Object.create。它的单参数版本可以通过简单的方式进行填充/填充:

if (!Object.create) {
    Object.create = function(proto, props) {
        if (typeof props !== "undefined") {
            throw new Error("The second argument of Object.create cannot be shimmed.");
        }
        function f() { }
        f.prototype = proto;
        return new f;
    };
}

我要注意,构造函数只是构建JavaScript中的对象层次结构的一种方式。它们不是唯一的方法,因为JavaScript使用原型继承。 JavaScript是如此强大,你可以使用构造函数来获得类似类继承的东西,但它也可以让你直接进行更传统的原型风格的继承。

¹“尽管JavaScript中没有任何内容使用constructor属性...”从ES2015(又名“ES6”)开始,这不再是真的。现在,constructor属性用于几个地方(例如SpeciesConstructorArraySpeciesCreate抽象操作),它们在各种类中使用,这些类具有返回类的新实例的方法,例如Array#slicePromise#then。它在那些地方用于确保子类正常工作:例如,如果你继承Array,并在子类的实例上使用slice,则slice返回的数组是一个实例您的子类,而不是原始Array - 因为slice使用ArraySpeciesCreate。