Javascript 构造函数属性的意义是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4012998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What it the significance of the Javascript constructor property?
提问by aaa90210
Trying to bend by head around Javascript's take on OO...and, like many others, running into confusion about the constructorproperty. In particular, the significance of the constructorproperty, as I can't seem to make it have any effect. E.g.:
试图绕过 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`.
In the above example, the object bseems to have had the right constructor called (Bar) – and it inherits the age property from Foo. So why do many people suggest this as a necessary step:
在上面的例子中,对象b似乎有一个正确的构造函数叫做 ( Bar)——它从Foo. 那么为什么很多人建议这是一个必要的步骤:
Bar.prototype.constructor = Bar;
Clearly, the right Barconstructor wascalled when constructing b, so what impact does this prototype property have? I am curious to know what practical difference it actually makes to have the constructor property set 'correctly'—as I can't see it having any affect on which constructor is actually called after an object is created.
显然,在Bar构造时调用了正确的构造函数b,那么这个原型属性有什么影响呢?我很想知道“正确”设置构造函数属性实际上有什么实际区别 - 因为我看不到它对创建对象后实际调用哪个构造函数有任何影响。
采纳答案by Tim Down
The constructorproperty makes absolutely no practical difference to anything internally. It's only any use if your code explicitly uses it. For example, you may decide you need each of your objects to have a reference to the actual constructor function that created it; if so, you'll need to set the constructorproperty explicitly when you set up inheritance by assigning an object to a constructor function's prototypeproperty, as in your example.
该constructor属性对内部的任何东西都没有实际影响。只有当您的代码明确使用它时,它才有任何用处。例如,您可能决定需要每个对象都引用创建它的实际构造函数;如果是这样,您需要在constructor通过将对象分配给构造函数的prototype属性来设置继承时显式设置属性,如您的示例所示。
回答by Jakob
Step one is to understand what constructorand prototypeare all about. It's not difficult, but one has to let go of "inheritance" in the classical sense.
第一步是了解什么是什么constructor,prototype都是关于什么的。这并不难,但必须放弃经典意义上的“继承”。
The constructor
构造函数
The constructorproperty does notcause any particular effects in your program, except that you can look at it to see which function was used in conjunction with the operator newto create your object. If you typed new Bar()it will be Barand you typed new Fooit will be Foo.
该constructor属性不会对您的程序产生任何特殊影响,只是您可以查看它以了解哪个函数与运算符结合使用new来创建您的对象。如果你输入new Bar()它将会是Bar你输入new Foo它将会是Foo。
The prototype
原型
The prototypeproperty is used for lookup in case the object in question does not have the property asked for. If you write x.attr, JavaScript will try to find attramong x's attributes. If it cant find it, it will look in x.__proto__. If it's not there either, it will look in x.__proto__.__proto__and so on as long as __proto__is defined.
prototype如果有问题的对象没有要求的属性,则该属性用于查找。如果您编写x.attr,JavaScript 将尝试查找attr其中x的属性。如果它找不到它,它会查找x.__proto__。如果它也不存在,它会在定义时查看x.__proto__.__proto__等等__proto__。
So what is __proto__and what has it got to do with prototype? Shortly put, prototypeis for "types" while __proto__is for "instances". (I say that with quotation marks because there's not really any difference between types and instances). When you write x = new MyType(), what happens (among other things) is that x.__proto___is set to MyType.prototype.
那么__proto__它是什么以及它有什么关系prototype呢?简而言之,prototype用于“类型”而__proto__用于“实例”。(我用引号这么说是因为类型和实例之间没有任何区别)。当您编写 时x = new MyType(),会发生什么(除其他外)x.__proto___设置为MyType.prototype。
The question
问题
Now, the above should be all you need to derive what your own example means, but to try and answer your actual question; "why write something like":
现在,以上应该是您推导出您自己的示例的含义所需要的全部内容,但要尝试回答您的实际问题;“为什么要写这样的东西”:
Bar.prototype.constructor = Bar;
Bar.prototype.constructor = Bar;
I personally have never seen it and I find it a little silly, but in the context you've given it will mean that the Bar.prototype-object (created by using new Foo(42)) will pose as have being created by Barrather than Foo. I suppose the idea is some make something similar to C++/Java/C#-like languages where a type-lookup (the constructorproperty) will always yield the most specific type rather than the type of the more generic object further up in the prototype-chain.
我个人从未见过它,我觉得它有点傻,但是在您给出的上下文中,这意味着Bar.prototype-object(通过 using 创建new Foo(42))将构成由Bar而不是Foo. 我想这个想法是一些类似于 C++/Java/C# 的语言,其中类型查找(constructor属性)将始终产生最具体的类型,而不是原型链中更高级的更通用对象的类型.
My advice: don't think very much about "inheritance" in JavaScript. The concepts of interfaces and mixins makes more sense. And don't check objects for their types. Check for the required properties instead ("if it walks like a duck and quacks like a duck, it's a duck").
我的建议是:不要过多考虑 JavaScript 中的“继承”。接口和混合的概念更有意义。并且不要检查对象的类型。改为检查所需的属性(“如果它像鸭子一样走路,像鸭子一样嘎嘎叫,它就是一只鸭子”)。
Trying to force JavaScript into a classical inheritance model, when all that it has is the prototype-mechanism as described above, is what causes the confusion. The many people that suggested to manually set the constructor-property probably tried to do just that. Abstractions are fine, but this manual assignment of the constructor property is not very idiomatic usage of JavaScript.
试图强制 JavaScript 进入经典的继承模型,当它所拥有的只是如上所述的原型机制时,是导致混淆的原因。许多建议手动设置constructor-property 的人可能试图这样做。抽象很好,但是构造函数属性的这种手动分配不是 JavaScript 的非常惯用的用法。
回答by Hyman Hu
one case to use constructor:
使用构造函数的一种情况:
this is one of the common realization of inheritance:
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; ... };this
new f()would not call the constructor of superClass,so when you create a subClass,maybe you need call the superClass at first,like this:SubClass = function() { SubClass.superClass.constructor.call(this); };
这是继承的常见实现之一:
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; ... };这
new f()不会调用superClass的构造函数,所以当你创建一个子类时,可能你首先需要调用superClass,像这样:SubClass = function() { SubClass.superClass.constructor.call(this); };
so the constructor property make sense here.
所以构造函数属性在这里有意义。
回答by golem
One of the use cases when you would want the prototype.constructorproperty to survive prototypeproperty reassignment is when you define a method on the prototypethat produces new instances of the same type as the given instance. Example:
您希望prototype.constructor属性在prototype属性重新分配后继续存在的用例之一是在 上定义一个方法,该方法prototype生成与给定实例具有相同类型的新实例。例子:
function Car() { }
Car.prototype.orderOneLikeThis = function() { // Clone producing function
return new this.constructor();
}
Car.prototype.advertise = function () {
console.log("I am a generic car.");
}
function BMW() { }
BMW.prototype = Object.create(Car.prototype);
BMW.prototype.constructor = BMW; // Resetting the constructor property
BMW.prototype.advertise = function () {
console.log("I am BMW with lots of uber features.");
}
var x5 = new BMW();
var myNewToy = x5.orderOneLikeThis();
myNewToy.advertise(); // => "I am BMW ..." if `BMW.prototype.constructor = BMW;` is not
// commented; "I am a generic car." otherwise.
回答by jsbisht
The constructor property points to the constructor that was used to create the object instance. If you typed 'new Bar()' it will be 'Bar' and you typed 'new Foo()' it will be 'Foo'.
构造函数属性指向用于创建对象实例的构造函数。如果您输入“new Bar()”,它将是“Bar”,而您输入“new Foo()”,它将是“Foo”。
But if you set the prototype without setting the constructor, you would get something like this:
但是如果你设置原型而不设置构造函数,你会得到这样的结果:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
var one = new Bar();
console.log(one.constructor); // 'Foo'
var two = new Foo();
console.log(two.constructor); // 'Foo'
To set the constructor actually to the constructor that was used to create the object, we need to set the constructor as well while setting prototype as follows:
要将构造函数实际设置为用于创建对象的构造函数,我们还需要在设置原型的同时设置构造函数,如下所示:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
Bar.prototype.constructor = Bar;
var one = new Bar();
console.log(one.constructor); // 'Bar'
var two = new Foo();
console.log(two.constructor); // 'Foo'

