我正在阅读this页面(特别是工厂部分)。
它提到避免使用new
关键字来防止意外遗忘的情况。它建议使用工厂。
Page新的示例:
function Bar() {
var value = 1;
return {
method: function() {
return value;
}
}
}
Bar.prototype = {
foo: function() {}
};
new Bar();
Bar(); // These are the same.
Page的工厂示例:
function Foo() {
var obj = {};
obj.value = 'blub';
var private = 2;
obj.someMethod = function(value) {
this.value = value;
}
obj.getPrivate = function() {
return private;
}
return obj;
}
工厂缺点:
避免new
以防止您忘记的问题是可以理解的。但我不太了解的是,他们说工厂的例子需要更多的内存,因为它没有使用原型功能。那么为什么不使用这样的东西呢?
我的解决方案:
var Foo = function () {
var foo = function () {
};
foo.prototype = {
bar: function () { }
};
return new foo();
};
问题:我错过了一些让这不是更好解决方案的东西吗?我的解决方案是否删除了工厂方法的列出缺点,为什么或为什么不呢?
答案 0 :(得分:1)
好的,让我们来看new
示例:
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
有一个名为__proto__
的属性。基本上,当您致电b.foo()
时,首先浏览器会查找名为foo
的方法。如果找不到,则会查看b.__proto__
和b.__proto__.__proto__
,依此类推。
注意:b.__proto__ === Bar.prototype
这意味着如果您反复拨打new Bar()
,他们将拥有相同的__proto__
,从而节省内存。 (这有副作用,如果你改变Bar.prototype
,它将改变Bar
__proto__
的所有实例。
让我们来看看你的工厂方法:
var Foo = function () {
var foo = function () {
};
foo.prototype = {
bar: function () { }
};
return new foo();
};
这不会节省内存,因为它会创建一个新的prototype
,每次一个新的构造函数就会调用Foo()
。换句话说,如果
var f1 = new Foo(), f2 = new Foo();
以下返回false:f1.constructor == f2.constructor
和f1.__proto__ == f2.__proto__
。这是什么意思?这意味着f1
和f2
不共享相同的prototype
,因此每次都必须复制对象。也许,你可以这样做:
var fooProto = {
callFoo: function() { alert("test"); }
};
function Foo() {
var foo = function() {};
foo.prototype = fooProto;
return new foo();
};
这将使用与常规构造函数相同的内存量。
边编辑:现代浏览器具有内置函数,在上一个示例中执行类似Foo
的操作。您可以使用Object.create(fooProto)
(但仅限于较新的浏览器)。
另外,请注意__proto__
在技术上是一个隐藏的只读属性(尽管某些浏览器允许您写入它)。它仅用于展示幕后发生的事情,不应该在实际代码中使用。