我有一个问题
据我所知,new
运算符以这种方式工作
function fakeNew(Ctor) {
var instance = Object.create(Ctor.prototype);
instance.constructor();
// I skip the conditional for simplicity
return instance;
}
这一切都是在我进行Object.create
polifill时开始的,所以我可以在不使用new
的情况下创建对象。
Object.create = function(proto) {
function F() { }
F.prototype = proto;
return new F();
}
我开始创建很多对象并对其进行原型设计,但是很多时候需要初始化它的属性我向它们做了.init()
方法
var base = {
init: function() {
EmitterMixin.call(this);
return this;
}
};
var obj = Object.create(base).init();
但是,当然,我不得不重新登记this
始终从.init()
返回{很多次我忘了或最糟糕,我忘了打电话给.init()
。因此,为了简化对象初始化,我想创建一个全局帮助器来执行它:调用Object.create
,调用初始化函数并返回它。
function create(proto) {
var child = Object.create(proto);
child.init();
return child;
}
当我意识到我在做什么实际上是 new
操作员做什么但是速度慢了的时候我才想碰到我的头。如果polifill适用,我甚至会使用new
。
所以我问自己,投掷new
有什么好处?它是主浏览器上的notably quicker,由于javascript性质,我们通常需要调用一个initualizer函数,而不是new
从它开始的事情。
最糟糕的是,我注意到我使用了两种不同类型的对象," abstract"和"实例",比我必须调用.init()
的实例更大的区别,而对于抽象它不是必需的,因为它们只会被用作其他对象的原型。我在使用new
:
function Foo() { }
Foo.prototype.method = function() { ... };
function Bar() { }
// "abstract" doesnt invoke initializer
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.other = function() { ... };
// "instance", the constructor is called as initializer
var obj = new Bar();
如果我们停止看new
,真的有什么好处吗?我们是否确定它不是一个更高级别的工具,而不是简化我们必须要做的事情?
您对new
和Object.create
有哪些优缺点?
答案 0 :(得分:1)
我尝试了两种方法,但我个人认为使用new
的传统方法没有任何问题。 Object.create
的主要论点是它使原型继承更加清晰 - 您不必理解函数构造函数上prototype
属性的复杂性以及它与对象的实际原型的关系。但它确实要求初始化是一个单独的步骤。
我首选的方法是将两种方法结合起来,例如:
function Animal(name) {
this.name = name || null;
}
Animal.prototype.eat = function() {
console.log('yum');
}
function Cat(name) {
Animal.call(this, name);
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.meow = function() {
console.log('meow');
}
var garfield = new Cat('garfield');
garfield.eat();
garfield.meow();
Object.create
此处的继承优于Cat.prototype = new Animal()
,原因有两个:
name
参数(如果未通过则抛出异常),您可以这样做,继承(Cat.prototype = Object.create(Animal.prototype)
)仍然有效。Cat
构造函数调用Animal
构造函数,那么Animal
构造函数创建的所有属性都将是未定义的,这样您就可以快速完成意识到错误。虽然这种方法(使用构造函数和new
)不那么“纯粹”原型,但它仍然是原型继承,只要你理解如何正确使用它就可以正常工作,并且需要更少的输入而不是Object.create
方法。
我在Javascript OO库simpleoo的文档中写了一些关于此的注释。 (注意:我可能很快就会为该库更改API;我正在链接它,主要是因为文档更详细地讨论了其中的一些概念。)