我知道这不是推荐的方法,但如果我声明以下函数,然后将它们作为构造函数调用,那么结果对象之间的区别(如果有的话)会是什么?
function Something() {
this.foo = "bar";
}
function something2() {
var that = {};
that.foo = "bar";
return that;
}
var x = new Something();
var y = new something2();
var z = something2();
即。 x
,y
和z
之间会有什么不同?
something2
是不是更好的编写构造函数的方法,因为你是否使用new
不会影响函数的结果?
BTW应something2
在这里大写? (我假设不是因为Crockford对资本化如此坚定,因为函数会破坏全局命名空间......)
答案 0 :(得分:15)
简而言之:
new something2() instanceof something2 === false
相关地,如果扩展您的示例以使用prototype属性
Something.prototype.method = function () { };
something2.prototype.method = function () { };
你会发现原型在后一种情况下不会继承:
typeof (new Something()).method === "function"
type (new something2()).method === "undefined"
真正的答案是你正在利用完全不同的底层机器。使用new
调用将调用[[Construct]]机制,该机制涉及根据构造函数的.prototype
属性设置[[Prototype]]属性。
但是[[Construct]]算法的步骤8--10中发生了一件有趣的事情:在设置一个新的空对象,然后附加其[[Prototype]]之后,它会执行[[Call]]到实际的构造函数,使用这个新的empty-plus-prototype对象作为this
。然后,在第9步中,如果事实证明该构造函数返回了某些东西---它抛弃了原型绑定的,传递为this
的对象,它花了所有时间设置!
注意:您可以使用.prototype
访问对象的[[Prototype]](与构造函数的Object.getPrototypeOf
不同):
Object.getPrototypeOf(new Something()) === Something.prototype // steps 5 & 6
Object.getPrototypeOf(new something2()) === Object.prototype // default
回答一些元问题:
something2
,因为它是工厂函数而不是构造函数。如果某些东西是大写的,那么它应该具有构造函数语义,例如new A() instanceof A
。"use strict";
放在文件的顶部。严格模式的许多很好的清理之一是this
默认为undefined
,而不是全局对象,所以例如在构造函数尝试将属性附加到new
时,调用不带undefined
的构造函数会导致错误。答案 1 :(得分:2)
在第二种情况下,返回的对象不会从构造函数继承任何内容,因此使用它没有什么意义。
> var x = new Something();
> var y = new something2();
> var z = something2();
即。 x,y和z之间的区别是什么?
x
继承自Something
,y
或z
都不会继承something2
。
不会有更好的方法来编写构造函数, 既然你是否使用新的不会影响结果 功能
将something2
作为构造函数调用是没有意义的,因为它返回的对象不是分配给this
的新构造对象,而是继承自something2.prototype
,这是其他的调用new something2()
时可能会得到。
顺便说一下,BTW应该在这里大写吗? (我假设没有 对于职能而言,克罗克福德对资本化非常坚定 clobber全局命名空间...)
不,因为将其称为构造函数是有点无意义的,因此将其描述为一个会产生误导。
答案 2 :(得分:1)
调用函数作为构造函数(即使用新的keyword
)运行以下步骤:
prototype
属性中的对象
this
是新对象)return
语句)所以,你的第二个解决方案只会返回一个带有属性" foo"的普通对象。但y
和z
都不是instanceof Something2
,也不会继承该原型。有这样的函数,是的,但它们不应该被称为构造函数(没有大写命名,没有new
的调用)。它们属于工厂模式。
如果你想要一个可以在没有new的情况下执行的构造函数,请使用该代码:
function Something(params) {
if (! this instanceof Something)
return new Something(params);
// else use "this" as usual
this.foo = "bar";
...
}
答案 3 :(得分:1)
我会说最重要的是返回对象的原型。
function Something() {
this.foo = "bar";
}
Something.prototype = {
// Something prototype code
hello: function(){
//...
}
}
function something2() {
var that = {};
that.foo = "bar";
return that;
}
something2.prototype = {
// something2 prototype code
greetings : function() {
//...
}
}
var x = new Something();
var y = new something2();
var z = something2();
typeof x.hello === function // should be true
typeof y.greetings === undefined // should be true
typeof z.greetings === undefined // should be true
换句话说,我说你没有用某些东西实例化对象,你正在创建从Object继承的纯粹新对象。
new something2效率低下,因为您正在创建一个空白范围,您可以从中创建一个新对象
var that = {};
相当于
var that = new Object();