我更喜欢me / that / self方法来解决Javascript中的绑定“问题”。我随时声明一个'类',它将具有可作为参数传递的函数(例如事件处理程序)。以下是我的一般设置示例:
function Person(name)
{
var me = this;
this.name = name;
this.alertName = function()
{
alert(me.name);
};
}
var aPerson = new Person('Paul');
setTimeout(aPerson.alertName, 1000);
这是有效的,因为我在'class'定义中定义了var me = this;
。这是重复的,所以作为练习,我想抽象一下并将me = this
定义添加到Function
的原型中,所以我不必每次都手动完成。我希望我描述它的方式是有道理的。我觉得这样的事情会奏效:
Function.prototype.me = function()
{
return this;
}
我期望在Person'类'中的任何地方调用我(),但事实并非如此。我尝试了不同的方法,例如将Function
扩展为具有定义的BaseFunction
类,但我无法弄清楚,我无法通过Google或其他方式找到任何内容SO。
如果你有兴趣,这里有一个jsFiddle我一直在玩的东西:
谢谢,
保
答案 0 :(得分:2)
您尝试使用me
的方式(如果我正确理解您的问题),它将被视为分配给内部变量的函数,而不是函数/“对象”的成员本身。
要访问me
原型,您必须使用this.me
- 这当然会让整个事情变得毫无意义。
var foo = function()
{
this.doSomething = function() {
alert('yay!');
};
// this doesn't work! "me" would refer to a non-existent variable
me.doSomething();
// this would work, but it's obviously useless.
this.me.doSomething();
}
更糟糕的是,如果您在另一个函数内定义的函数内调用this.me
,您将访问内部函数的this.me
,并且永远不能使用此方法访问外部函数
答案 1 :(得分:2)
您尝试定义me
的方式是说您需要更加了解this
。
函数的原型 - 是由new
创建的所有对象的原型链。它完全不知道你的具体对象。
根据调用的位置调用处理程序,而不是您定义它的位置。 因此,没有从处理程序本身到它所属的对象的链接。
如何定义特定this
并将其绑定到函数以便能够将其全部传递的方式,除了将this
存储在闭包中之外,就像现在一样,是{{ 1}}功能。你可以这样做:
.bind()
实际上这是最真实的'如何在JS中完成它。当然有很多糖库可以用不同的形式包裹它们,但是所有的都有var foo = function (name) {
this.name = name;
this.handler = function () {
console.log('I am called, name=', this.name);
}.bind(this);
}
var boo = new foo('Paul');
setTimeout(boo.handler, 1000)
。
但是,如果你担心有重复的bind
,那么任何其他选项对你来说也会是重复 :)检查CoffeeScript - 它是梦想的简约编码和梦魇来自其他方面。
答案 2 :(得分:1)
您可能知道在构造函数中定义的事件处理函数(或示例中的常规方法)将始终可以访问构造函数通过闭包调用的参数吗?试试这个。
function Person(name){
this.alertName = function(){
alert(name);
};
}
这种模式的缺点是你不能将alertName放在Person的原型上,因为它需要通过闭包来访问私有参数。如果您不使用闭包,则绝对不需要在Person的每个实例上创建新的警报名称函数。
编辑:更正。 getter和setter同样糟糕,因为它们将闭包保留在内存中就像一个方法,没有想到它。因此,除非你真正好好利用它,否则你应该完全避免使用它,并在有疑问时使用原型。
<击>
您需要getter和setter来发布按值传递的变量。通过引用传递的变量可以通过this.yourPropertyName = yourArgumentName
发布,因为它们只会引用同一个对象。
Object.defineProperty(this,"name",{
get:function(){return name},
set:function(newName){name = newName}
});
击> <击> 撞击> 你不应该本身绑定它,而不是使用“this”。特别是在可能的情况下,您应该将它们放在原型上,并使它们成为通用的。术语“鸭型”通常用于此。因为如果你在你的方法中使用“this”,任何具有“name”属性的东西都可以使用Person.prototype.callName,它就会起作用(即使它是一个鸭子)。
答案 3 :(得分:0)
如果你发现JavaScript过于冗长,那就是CoffeeScript:
class Person
constructor: (@name) ->
alertName: => alert "Hi, my name is #{@name}"
aPerson = new Person 'chka chka Slim Shady'
setTimeout aPerson.alertName, 1000
这使用胖箭头(=>
),确保@
(== this
}绑定到正确的上下文。