JavaScript将Object.prototype
定义为为类类对象定义方法或属性的方法。
使用Object.prototype
时存在的一个大问题是,当通过回调调用方法时,不正确行为,因为this
将具有调用上下文。
function Foo() {}
Foo.prototype.resize() {
console.log(this);
}
var foo = new Foo();
window.on('resize', foo.resize);
因此,要解决此限制,我们可以执行以下操作。
function Foo2() {
function resize() {
console.log(self);
}
var self = this;
this.resize = resize;
}
var foo2 = new Foo2();
window.on('resize', foo2.resize);
鉴于上述情况,似乎始终在示例2中定义类类对象似乎更好。
因此,我们何时应该使用Object.prototype
设施?我的意思是,你不能先了解如何调用你的方法,并且在调用时你肯定会想要正确的this
上下文引用。
支持上下文:我想到了这个问题,因为您似乎正在使用Object.prototype
创建实例方法。但是,如图所示,你不是。您只是创建没有"真实"连接到他们的实例。因此需要使用closure来创建实例绑定方法。此外,在阅读this excellent explanation of this
后,我们想到了这个问题。
答案 0 :(得分:3)
您的困惑来自于您将JavaScript对象视为具有OOP语言之类的方法。所以你认为他们应该有固定的上下文,因为OOP语言中的方法通常使用"早期绑定"因此他们受到正确背景的约束。它与JavaScript有所不同。它是一种"后期绑定",当函数的上下文 - this
- 在执行函数时确定。对我来说,将方法视为指向函数的简单对象属性是有益的,这确实可以在不同的上下文中执行。例如,我们可以这样:
function resize() {
console.log(this);
}
resize.call(window);
resize.call(custom);
如果你愿意,当然你可以实现"早期绑定"使用bind
例如:
function O() {
this.resize = function() {}.bind(this);
}
var o = new O();
但这限制了对象方法的可重用性。例如,这是不可能的:
Array.prototype.slice.call(arguments)
您可以阅读here,了解即使在ES6中方法未受约束的原因。
原型不是static methods
,它们是为了实现内存有效的代码重用而创建的。正如JLRishe
指出的那样,原型的最大优点是减少了内存使用量,因为你可以在原型上定义一个函数的一个实例,并且方便访问它作为具有他们的原型链中的原型。但原型只是为了方便。以下是resize
没有prototype
的示例:
// here only one instance of `resize` function is created
function resize() {
console.log(this);
}
var o1 = {
resize: resize
}
var o2 = {
resize: resize
}
您只是创建没有"真实"连接到 他们的实例。
正确,这是一个带有"方法的原型示例"以后用于不同的上下文:
var prototype = {
resize: function() {
console.log(this);
}
}
var o1 = {
resize: resize
}
Object.setPrototypeOf(o1, prototype);
var o2 = {
resize: resize
}
Object.setPrototypeOf(o2, prototype);
我认为JavaScript是在构思时考虑到函数是第一类对象,而不是对象应该具有正确绑定上下文的方法。
静态方法通常作为函数构造函数的属性实现,如下所示:
function SomeObjectConstructor() {}
SomeObjectConstructor.someStaticMethod = function() {}
答案 1 :(得分:1)
我认为尽可能直接将对象的方法绑定到事件处理程序是您想要避免的捷径。
window.on('resize', function () {
foo.resize();
});
尽管它比较冗长,但我认为编写这样的处理程序更加清晰,不会影响this
方法中Object.prototype
的上下文。
正如其中一条评论中所述,使用对象的原型比为对象的每个实例定义方法更有效。