我有一个问题想问你
据我所知,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();
}
我开始创建很多对象并制作它们的原型(prototype),但是很多时候需要初始化它的属性我对它们做了一个 .init()
方法
var base = {
init: function() {
EmitterMixin.call(this);
return this;
}
};
var obj = Object.create(base).init();
但是当然,我不得不记住总是从 .init()
返回 this
并且很多时候我忘记了它或者最糟糕的是,我忘记调用 .init()
。因此,为了简化对象初始化,我想创建一个全局助手来完成它:调用 Object.create
,调用初始化函数并返回它。
function create(proto) {
var child = Object.create(proto);
child.init();
return child;
}
当我意识到我所做的实际上是 new
运算符所做的 时,我想撞墙,但速度要慢得多。如果 polifill 适用,我什至会在后台使用 new
。
所以我问自己,throw new
有什么好处?这是notably quicker在主流浏览器上,由于 javascript 的特性,我们通常需要调用一个初始化函数,而不是 new
从一开始就做的事情。
最糟糕的是,我注意到我使用了两种不同类型的对象,“抽象”和“实例”,更大的区别是我必须调用 .init 的实例()
而对于抽象来说,这不是必需的,因为它们只会被用作其他对象的原型(prototype)。我已经在使用 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
有哪些优点/缺点?
最佳答案
我已经尝试了这两种方法,我个人认为使用 new
的传统方法没有任何问题。 Object.create
的主要论点是它使原型(prototype)继承更加清晰 - 您不必理解函数构造函数上的 prototype
属性的复杂性以及它是如何实现的与对象的实际原型(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)
) 仍然有效。 - 如果您忘记从
Animal
构造函数中调用Cat
构造函数,所有本应由Animal
构造函数创建的属性将改为未定义,让您快速意识到错误。
虽然这种方法(使用构造函数和 new
)不是“纯粹”的原型(prototype),但它仍然是原型(prototype)继承,只要您了解如何正确使用它,它就可以正常工作,并且需要与 Object.create
方法相比,输入更少。
我在我的 Javascript OO 库的文档中写了一些关于此的其他注释,simpleoo . (注意:我可能很快会更改该库的 API;我链接到它主要是因为文档更详细地讨论了其中的一些概念。)
关于javascript - 我们真的必须改成 Object.create 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16080691/