在MDN文章《面向对象Javascript介绍》中关于继承的部分,我注意到他们设置了prototype.constructor:
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
这有什么重要的目的吗?可以省略吗?
在MDN文章《面向对象Javascript介绍》中关于继承的部分,我注意到他们设置了prototype.constructor:
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
这有什么重要的目的吗?可以省略吗?
当前回答
下面是MDN的一个例子,我发现它对理解它的用法很有帮助。
在JavaScript中,我们有返回AsyncFunction对象的async函数。AsyncFunction不是一个全局对象,但可以通过使用构造函数属性检索它并利用它。
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
// AsyncFunction constructor
var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor
var a = new AsyncFunction('a',
'b',
'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);');
a(10, 20).then(v => {
console.log(v); // prints 30 after 4 seconds
});
其他回答
下面是MDN的一个例子,我发现它对理解它的用法很有帮助。
在JavaScript中,我们有返回AsyncFunction对象的async函数。AsyncFunction不是一个全局对象,但可以通过使用构造函数属性检索它并利用它。
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
// AsyncFunction constructor
var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor
var a = new AsyncFunction('a',
'b',
'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);');
a(10, 20).then(v => {
console.log(v); // prints 30 after 4 seconds
});
它并不总是必要的,但它确实有它的用途。假设我们想在基类Person上创建一个复制方法。是这样的:
// define the Person Class
function Person(name) {
this.name = name;
}
Person.prototype.copy = function() {
// return new Person(this.name); // just as bad
return new this.constructor(this.name);
};
// define the Student class
function Student(name) {
Person.call(this, name);
}
// inherit Person
Student.prototype = Object.create(Person.prototype);
现在,当我们创建一个新的Student并复制它时会发生什么?
var student1 = new Student("trinth");
console.log(student1.copy() instanceof Student); // => false
副本不是Student的实例。这是因为(如果没有显式检查),我们将无法从“基”类返回Student副本。我们只能返回Person。然而,如果我们重置了构造函数:
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
...然后一切都按照预期进行:
var student1 = new Student("trinth");
console.log(student1.copy() instanceof Student); // => true
得到了一个很好的代码示例,为什么真的有必要设置原型构造函数..
function CarFactory(name){
this.name=name;
}
CarFactory.prototype.CreateNewCar = function(){
return new this.constructor("New Car "+ this.name);
}
CarFactory.prototype.toString=function(){
return 'Car Factory ' + this.name;
}
AudiFactory.prototype = new CarFactory(); // Here's where the inheritance occurs
AudiFactory.prototype.constructor=AudiFactory; // Otherwise instances of Audi would have a constructor of Car
function AudiFactory(name){
this.name=name;
}
AudiFactory.prototype.toString=function(){
return 'Audi Factory ' + this.name;
}
var myAudiFactory = new AudiFactory('');
alert('Hay your new ' + myAudiFactory + ' is ready.. Start Producing new audi cars !!! ');
var newCar = myAudiFactory.CreateNewCar(); // calls a method inherited from CarFactory
alert(newCar);
/*
Without resetting prototype constructor back to instance, new cars will not come from New Audi factory, Instead it will come from car factory ( base class ).. Dont we want our new car from Audi factory ????
*/
给定简单构造函数:
function Person(){
this.name = 'test';
}
console.log(Person.prototype.constructor) // function Person(){...}
Person.prototype = { //constructor in this case is Object
sayName: function(){
return this.name;
}
}
var person = new Person();
console.log(person instanceof Person); //true
console.log(person.sayName()); //test
console.log(Person.prototype.constructor) // function Object(){...}
默认情况下(来自规范https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor),所有原型都会自动获得一个称为constructor的属性,该属性指向属性所在的函数。 根据构造函数的不同,可能会将其他属性和方法添加到原型中,这不是很常见的做法,但仍然允许进行扩展。
所以简单地回答:我们需要确保原型中的值。构造函数被正确地设置为规范所假定的样子。
我们必须总是正确地设置这个值吗?它有助于调试,并使内部结构与规范保持一致。当我们的API被第三方使用时,我们肯定应该这样做,但当代码最终在运行时执行时,我们不应该这样做。
到目前为止,困惑仍然存在。
按照原来的例子,你有一个现有的对象student1 as:
var student1 = new Student("Janet", "Applied Physics");
假设你不想知道student1是如何创建的,你只是想要另一个类似的对象,你可以使用student1的构造函数属性:
var student2 = new student1.constructor("Mark", "Object-Oriented JavaScript");
在这里,如果没有设置构造函数属性,它将无法从Student获取属性。相反,它将创建一个Person对象。