JavaScript避免新关键字
我在读佩奇(尤其是工厂部分) 它提到要避免使用JavaScript避免新关键字,javascript,new-operator,Javascript,New Operator,我在读佩奇(尤其是工厂部分) 它提到要避免使用new关键字,以防止意外忘记它。它建议使用工厂 页面的新示例: function Bar() { var value = 1; return { method: function() { return value; } } } Bar.prototype = { foo: function() {} }; new Bar(); Bar(); // These
new
关键字,以防止意外忘记它。它建议使用工厂
页面的新示例:
function Bar() {
var value = 1;
return {
method: function() {
return value;
}
}
}
Bar.prototype = {
foo: function() {}
};
new Bar();
Bar(); // These are the same.
function Foo() {
var obj = {};
obj.value = 'blub';
var private = 2;
obj.someMethod = function(value) {
this.value = value;
}
obj.getPrivate = function() {
return private;
}
return obj;
}
var Foo = function () {
var foo = function () {
};
foo.prototype = {
bar: function () { }
};
return new foo();
};
页面的工厂示例:
function Bar() {
var value = 1;
return {
method: function() {
return value;
}
}
}
Bar.prototype = {
foo: function() {}
};
new Bar();
Bar(); // These are the same.
function Foo() {
var obj = {};
obj.value = 'blub';
var private = 2;
obj.someMethod = function(value) {
this.value = value;
}
obj.getPrivate = function() {
return private;
}
return obj;
}
var Foo = function () {
var foo = function () {
};
foo.prototype = {
bar: function () { }
};
return new foo();
};
工厂缺点:
- 因为创建的对象不共享原型上的方法,所以它使用了更多的内存
- 为了继承,工厂需要从另一个对象复制所有方法,或者将该对象放在新对象的原型上
- 仅仅因为遗漏了一个新关键字而放弃原型链,这与语言的精神背道而驰
新的
,以防止您忘记时出现问题,这是可以理解的。但我不太明白的是,他们说工厂示例需要更多内存,因为它没有使用原型函数。那么为什么不用这样的东西来代替呢
我的解决方案:
function Bar() {
var value = 1;
return {
method: function() {
return value;
}
}
}
Bar.prototype = {
foo: function() {}
};
new Bar();
Bar(); // These are the same.
function Foo() {
var obj = {};
obj.value = 'blub';
var private = 2;
obj.someMethod = function(value) {
this.value = value;
}
obj.getPrivate = function() {
return private;
}
return obj;
}
var Foo = function () {
var foo = function () {
};
foo.prototype = {
bar: function () { }
};
return new foo();
};
问题:我是否遗漏了一些使这不是更好的解决方案的东西?我的解决方案是否消除了工厂方法中列出的缺点,原因是什么?好的,让我们以
新的
为例:
function Bar() {
var value = 1;
// Whoops, sorry
// As Bergi points out, if you have a return value then that overrides the normal object that is returned by new
// Didn't even notice you have a return in here!
/*
return {
method: function() {
return value;
}
}
*/
// This does the same thing (approximately) but now calling "(new Bar()) instanceof Bar" will be true
this.method = function() {
return value;
};
}
Bar.prototype = {
foo: function() {}
};
var b = new Bar();
在google chrome控制台中,b
有一个名为\uuuu proto\uuu
的属性。基本上,当您调用b.foo()
时,浏览器首先查找名为foo
的方法。如果没有找到它,它会在b.\uuuuu-proto\uuuuu
和b.\uuuuu-proto\uuuu.\uuuuu
中查找,依此类推
注意:
b.\uuuu proto\uuuu==Bar.prototype
这意味着如果您反复调用newbar()
,它们都将具有相同的\uuuu proto\uuuu
,从而节省内存。(这样做的副作用是,如果您对Bar.prototype
进行变异,它也会更改Bar
的\uu proto\uu
的所有实例)
让我们看看您的工厂方法:
var Foo = function () {
var foo = function () {
};
foo.prototype = {
bar: function () { }
};
return new foo();
};
这不会节省内存,因为每次调用Foo()
,它都会创建一个新的原型和一个新的构造函数。换句话说,如果
var f1 = new Foo(), f2 = new Foo();
以下返回false:f1.constructor==f2.constructor
和f1.\uuuu proto\uuuu==f2.\uuuu proto\uu
。这是什么意思?这意味着f1
和f2
不共享相同的原型
,因此每次都必须复制对象。或许,您可以这样做:
var fooProto = {
callFoo: function() { alert("test"); }
};
function Foo() {
var foo = function() {};
foo.prototype = fooProto;
return new foo();
};
这将使用与常规构造函数相同的内存量
侧边编辑:现代浏览器有一个内置功能,类似上一个示例中的Foo
。您可以使用Object.create(fooProto)
(但只能在较新的浏览器中使用)
另外,请注意,\uuuu proto\uuu
在技术上是一个隐藏的只读属性(尽管有些浏览器允许您对其进行写入)。它只是为了显示幕后的情况,不应该在实际代码中使用。是的,每次调用工厂方法时都会创建一个新的构造函数。我稍微澄清了我的问题。我知道我的每次都创建了一个新对象,我只是好奇它是否删除了链接站点(我现在的问题中包括了)列出的工厂方法的缺点。或者在这个问题上添加了任何赞成/反对意见。正如所有这些代码片段所显示的,还有更糟糕的事情可能出错。要对抗遗忘的new
s.1。将foo
和foo.prototype
移动到foo
函数之外是否可以解决这个问题?2.感谢您解释\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?构造函数返回一个对象,原型将被忽略。为了清晰起见,您应该始终使用对象。创建。如果需要的话,在旧浏览器中填充它。@Bergi(注释1)我说的是第一个示例,您使用var b=new Bar()代码>。然后b.。\uuuu proto\uuuu==Bar.prototype
@Shelby115:是的,这会有帮助。实际上,有一个函数makeFoo(){return new Foo();}
,与Foo
相反,它可以在没有new
的情况下使用,这并不少见。请注意,构造函数名称应始终大写。