Javascript 为什么需要设置原型构造函数?
在中,我注意到他们设置了prototype.constructor:Javascript 为什么需要设置原型构造函数?,javascript,oop,inheritance,Javascript,Oop,Inheritance,在中,我注意到他们设置了prototype.constructor: // correct the constructor pointer because it points to Person Student.prototype.constructor = Student; // correct the constructor pointer because it points to Person Student.prototype.constructor = Student; 这
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
这有什么重要意义吗?省略它可以吗?编辑,实际上我错了。注释这一行根本不会改变它的行为。(我测试了一下)
是的,这是必要的。当你这样做的时候
Student.prototype = new Person();
Student.prototype.constructor
变成Person
。因此,调用Student()
将返回由Person
创建的对象。如果你这样做的话
Student.prototype.constructor = Student;
Student.prototype.constructor
被重置回Student
。现在,当您调用Student()
时,它执行Student
,调用父构造函数parent()
,它返回正确继承的对象。如果在调用它之前没有重置Student.prototype.constructor
,则会得到一个对象,该对象在Student()
编辑中没有设置任何属性,实际上我错了。注释这一行根本不会改变它的行为。(我测试了一下)
是的,这是必要的。当你这样做的时候
Student.prototype = new Person();
Student.prototype.constructor
变成Person
。因此,调用Student()
将返回由Person
创建的对象。如果你这样做的话
Student.prototype.constructor = Student;
Student.prototype.constructor
被重置回Student
。现在,当您调用Student()
时,它执行Student
,调用父构造函数parent()
,它返回正确继承的对象。如果在调用它之前没有重置Student.prototype.constructor
,则会得到一个对象,该对象不会在Student()
中设置任何属性。没有必要设置原型。获取完全相同的代码,但删除prototype.constructor行。有什么变化吗?否。现在,进行以下更改:
Person = function () {
this.favoriteColor = 'black';
}
Student = function () {
Person.call(this);
this.favoriteColor = 'blue';
}
在测试代码的末尾
alert(student1.favoriteColor);
颜色是蓝色的
根据我的经验,对prototype.constructor的更改不会有多大作用,除非您正在做非常具体、非常复杂的事情,而这些事情可能不是很好的实践:)
编辑:
在浏览了一下网页并做了一些实验之后,人们似乎设置了构造器,使其“看起来”像是用“new”构造的东西。我想我会说,这个问题在于javascript是一种原型语言——没有继承这回事。但是大多数程序员的编程背景都将继承作为“方法”。因此,我们想出了各种各样的办法,试图使这种原型语言成为一种“经典”语言。。例如扩展“类”。事实上,在他们给出的例子中,一个新学生是一个人,而不是从另一个学生那里“延伸”。。学生就是这个人,不管这个人是什么,学生也是。扩展学生,无论你扩展了什么,在本质上都是一个学生,但都是根据你的需要定制的
Crockford有点疯狂和过分热情,但是认真阅读他写的一些东西。。这会让你对这件事有不同的看法。我不同意。没有必要设置原型。获取完全相同的代码,但删除prototype.constructor行。有什么变化吗?否。现在,进行以下更改:
Person = function () {
this.favoriteColor = 'black';
}
Student = function () {
Person.call(this);
this.favoriteColor = 'blue';
}
在测试代码的末尾
alert(student1.favoriteColor);
颜色是蓝色的
根据我的经验,对prototype.constructor的更改不会有多大作用,除非您正在做非常具体、非常复杂的事情,而这些事情可能不是很好的实践:)
编辑:
在浏览了一下网页并做了一些实验之后,人们似乎设置了构造器,使其“看起来”像是用“new”构造的东西。我想我会说,这个问题在于javascript是一种原型语言——没有继承这回事。但是大多数程序员的编程背景都将继承作为“方法”。因此,我们想出了各种各样的办法,试图使这种原型语言成为一种“经典”语言。。例如扩展“类”。事实上,在他们给出的例子中,一个新学生是一个人,而不是从另一个学生那里“延伸”。。学生就是这个人,不管这个人是什么,学生也是。扩展学生,无论你扩展了什么,在本质上都是一个学生,但都是根据你的需要定制的
Crockford有点疯狂和过分热情,但是认真阅读他写的一些东西。。这会让你对这些东西有不同的看法。这并不总是必要的,但它确实有它的用途。假设我们想在base
Person
类上创建一个copy方法。像这样:
// 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);
现在,当我们创建一个新的学生并复制它时会发生什么
var student1 = new Student("trinth");
console.log(student1.copy() instanceof Student); // => false
该副本不是学生
的实例。这是因为(没有显式检查),我们无法从“基类”返回Student
副本。我们只能返回个人
。但是,如果我们重置了构造函数:
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// 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
它并不总是必要的,但它确实有它的用途。假设我们想在basePerson
类上创建一个copy方法。像这样:
// 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);
现在,当我们创建一个新的学生并复制它时会发生什么
var student1 = new Student("trinth");
console.log(student1.copy() instanceof Student); // => false
该副本不是学生
的实例。这是因为(没有显式检查),我们无法从“基类”返回Student
副本。我们只能返回个人
。但是,如果我们重置了构造函数:
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// 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 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 ????
*/
这
/* This sets up the prototypal delegation correctly
*so that if a lookup fails on Student.prototype, it would delegate to Person's .prototype
*This also allows us to add more things to Student.prototype
*that Person.prototype may not have
*So now a failed lookup on an instance of Student
*will first look at Student.prototype,
*and failing that, go to Person.prototype (and failing /that/, where do we think it'll go?)
*/
Student.prototype = Object.create(Person.prototype);
// Now we fix what the .constructor property is pointing to
Student.prototype.constructor = Student
// If we check instanceof here
console.log(eve instanceof Person) // true
class Person {
// constructor function here
constructor(name, age) {
this.name = name;
this.age = age;
}
// static getter instead of a static property
static get species() {
return 'human';
}
}
class Student extends Person {
constructor(name, age, school) {
// calling the superclass constructor
super(name, age);
this.school = school;
}
}
const Person = {
name: '[Person.name]',
greeting: function() {
console.log( `My name is ${ this.name || '[Name not assigned]' }` );
}
};
// Person.greeting = function() {...} // or define outside the obj if you must
// Object.create version
const john = Object.create( Person );
john.name = 'John';
console.log( john.name ); // John
john.greeting(); // My name is John
// Define new greeting method
john.greeting = function() {
console.log( `Hi, my name is ${ this.name }` )
};
john.greeting(); // Hi, my name is John
// Object.assign version
const jane = Object.assign( Person, { name: 'Jane' } );
console.log( jane.name ); // Jane
// Original greeting
jane.greeting(); // My name is Jane
// Original Person obj is unaffected
console.log( Person.name ); // [Person.name]
console.log( Person.greeting() ); // My name is [Person.name]
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(){...}
Student.prototype.constructor = Student;
Person.prototype.copy = function() {
// return new Person(this.name); // just as bad
return new this.constructor(this.name);
};
Person.prototype.copy = function() {
// return new Person(this.name); // just as bad
return new Person(this.name);
};
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
});