aaa*_*210 118 javascript constructor prototype
试图绕过Javascript对OO的看法......和许多其他人一样,对constructor财产产生混淆.特别是constructor财产的重要性,因为我似乎无法使其产生任何影响.例如:
function Foo(age) {
this.age = age;
}
function Bar() {
Foo.call(this, 42);
this.name = "baz";
}
Bar.prototype = Object.create(Foo.prototype);
var b = new Bar;
alert(b.constructor); // "Foo". That's OK because we inherit `Foo`'s prototype.
alert(b.name); // "baz". Shows that Bar() was called as constructor.
alert(b.age); // "42", inherited from `Foo`.
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,对象b似乎有正确的构造函数call(Bar) - 并且它继承了age属性Foo.那么为什么许多人认为这是必要的步骤:
Bar.prototype.constructor = Bar;
Run Code Online (Sandbox Code Playgroud)
显然,Bar构造时会调用正确的构造函数b,因此这个原型属性有什么影响?我很想知道它实际上使构造函数属性设置'正确'有什么实际区别 - 因为我无法看到它对创建对象后实际调用的构造函数有任何影响.
Jak*_*kob 99
第一步是了解什么constructor和prototype所有.这并不困难,但人们不得不放弃传统意义上的"继承".
构造函数
该constructor属性不会在程序中产生任何特殊效果,除了您可以查看它以查看与操作符一起使用哪个函数new来创建对象.如果你键入new Bar()它将是Bar,你输入new Foo它将是Foo.
原型
prototype如果相关对象没有要求的属性,则该属性用于查找.如果你写x.attr,JavaScript就试图找到attr其中x的属性.如果它找不到它,它会查看x.__proto__.如果它不存在,x.__proto__.__proto__只要__proto__定义它就会查看等等.
那么__proto__它与它有什么关系prototype呢?简而言之,prototype是"类型",而__proto__"实例".(我用引号说,因为类型和实例之间没有任何区别).当你写作时x = new MyType(),发生的事情(以及其他事情)x.__proto___是设置的MyType.prototype.
这个问题
现在,上面应该是你需要得出你自己的例子意味着什么,但试图回答你的实际问题; "为什么要这样写":
Bar.prototype.constructor = Bar;
我个人从来没有见过它,我发现它有点愚蠢,但在你给出它的上下文中,意味着Bar.prototype-object(通过使用创建new Foo(42))将构成由Bar而不是创建Foo.我想这个想法有些类似于C++/Java/C#类似的语言,其中类型查找(constructor属性)将始终产生最具体的类型,而不是原型链中更通用的对象的类型.
我的建议:不要过多考虑JavaScript中的"继承".接口和mixin的概念更有意义.并且不要检查对象的类型.检查所需的属性("如果它像鸭子一样走路,像鸭子一样呱呱叫,它是一只鸭子").
试图强制JavaScript进入经典的继承模型,当它具有如上所述的原型机制时,就会引起混淆.建议手动设置constructor-property 的许多人可能试图这样做.抽象很好,但是构造函数属性的这种手动赋值并不是非常惯用的JavaScript.
Tim*_*own 70
该constructor物业对内部任何事物都没有实际的区别.只有在您的代码明确使用它时,它才有用.例如,您可能决定需要每个对象都具有对创建它的实际构造函数的引用; 如果是这样,您需要constructor通过将对象分配给构造函数的prototype属性来设置继承时显式设置该属性,如您的示例所示.
小智 10
一个使用构造函数的情况:
这是继承的常见实现之一:
Function.prototype.extend = function(superClass,override) {
var f = new Function();
f.prototype = superClass.prototype;
var p = this.prototype = new f();
p.constructor = this;
this.superclass = superClass.prototype;
...
};
Run Code Online (Sandbox Code Playgroud)这new f()不会调用superClass的构造函数,所以当你创建一个subClass时,你可能需要先调用superClass,如下所示:
SubClass = function() {
SubClass.superClass.constructor.call(this);
};
Run Code Online (Sandbox Code Playgroud)所以构造函数属性在这里有意义.
此处的先前答案(以各种方式)说 constructor JavaScript 本身中的任何内容都未使用该属性的值。写这些答案时确实如此,但 ES2015 及以后的版本已开始 constructor 用于事物。
函数的 constructor 属性的prototype属性旨在指向函数,以便您可以询问对象是什么构造了它。它作为创建传统函数对象或类构造函数对象(详细信息)的一部分自动设置。
function TraditionalFunction() {
}
console.log(TraditionalFunction.prototype.constructor === TraditionalFunction); // true
class ExampleClass {
}
console.log(ExampleClass.prototype.constructor === ExampleClass); // trueRun Code Online (Sandbox Code Playgroud)
箭头函数没有prototype属性,因此它们没有prototype.constructor.
多年来,JavaScript 规范只说 constructor 默认情况下该属性将存在并具有该值(返回该函数的链接)。但是从 ES2015 开始,这种情况发生了变化,规范中的各种操作现在实际使用了该 constructor 属性,例如this、this、this和this。
因此,在设置构建继承链的构造函数时,最好确保该 constructor 属性引用适当的函数。有关示例等,请在此处查看我的答案。