我有以下问题:
我正在尝试覆盖一个函数,然后使用angular($scope.$apply()
)来应用它,但我的this
- 上下文似乎不是正确的。
原始函数(在另一个文件中)如下所示:
Anno.prototype.switchTo = function(otherAnno) {
if (otherAnno != null) {
this.hideAnno();
return otherAnno.show();
} else {
console.warn("Can't switchTo a null object. Hiding instead.");
return this.hide();
}
};
然后在另一个文件中,我“覆盖”它,如下所示:
var switchToFunction = AnnoModule.Anno.prototype.switchTo;
AnnoModule.Anno.prototype.switchTo = function(otherAnno) {
switchToFunction(otherAnno);
$scope.$apply();
};
所以实际上我保存了原始函数,然后重新定义原始函数以调用原始函数,然后应用范围。
现在出现了问题:正如你所看到的,该函数使用了this.hideAnno()
,但在我的重新定义的函数中,上下文是另一个,这就是为什么chrome会抛出错误“this.hideAnno()不是一个功能“。但现在我不确定如何才能获得正确的背景。我试图理解this,但我发现JavaScript非常混乱,我真的不明白。
有人可以帮我理解JavaScript混乱吗?
答案 0 :(得分:1)
当一个函数作为js中的方法被调用时,它内部的this
引用该方法所属的对象。
另一方面,当一个函数自己被调用时,它内部的this
引用全局对象或严格模式下的undefined
。
您正在将定义为方法的函数提取(然后调用)到独立函数中,这就是为什么this
没有达到预期的效果。
在这种情况下,您需要call或apply switchToFunction
,将this
的值设置为您需要的值。换句话说,您将旧方法的this
设置为您创建的新方法的this
:
var switchToFunction = AnnoModule.Anno.prototype.switchTo;
AnnoModule.Anno.prototype.switchTo = function(otherAnno, that) {
switchToFunction.call(this, otherAnno); // sets `this` of the old method to be this of the new method you created
$scope.$apply();
};
答案 1 :(得分:1)
要理解这个问题,我认为首先我们应该了解this
关键字的工作原理以及如何调整它。
在JavaScript中,任何函数内的
this
对象都是对象,在其上调用方法。
考虑以下示例,
var obj1 = {
foo: function() {
console.log(this);
}
};
function bar() {
console.log(this);
}
现在调用方法时,我们得到如下输出
obj1.foo(); // obj1
bar(); // window
由于在
foo
上调用了obj1
方法,因此this
方法中的foo
变为obj1
。同样,this
方法中的bar
将是window
对象。
现在,如果我想在函数内部调用bar
obj1
作为this
,该怎么办?为此,JavaScript提供了call, apply and bind
方法来动态更改函数的this
。让我们看看如何使用call
方法实现这一目标。
bar.call(obj1); // obj1
类似地,
obj1.foo.call(window); // window
call
方法将thisArg
对象作为参数,this
函数内的bar
。如果bar
函数还希望参数也可以通过call
之后的thisArg
方法传递。有关call
。
所以问题的解决方案将是,
var switchToFunction = AnnoModule.Anno.prototype.switchTo;
AnnoModule.Anno.prototype.switchTo = function(otherAnno) {
switchToFunction.call(this, otherAnno);
$scope.$apply();
};
希望这能让你明白这个问题。