我知道如何使用这些方法来改变函数/方法调用的上下文:apply,bind,call。我的问题是,有没有办法检查函数/方法是否已经设置了它的上下文?
// given
var beta;
function alpha () {
return this;
}
function isContextSet (fn) {
/* check for context binding on fn */
}
beta = alpha.bind("hello");
isContextSet(alpha); // returns false
isContextSet(beta); // returns true
我想我已经知道了答案,但我想无论如何我会问,如果没有其他原因:1。确认我的假设,或2.学到一些东西。我确信我不是第一个提出这个问题的人,但我不知道如何找到答案,因为我得到的是对如何使用的回应:.apply(),. call()或。绑定()。
答案 0 :(得分:2)
没有
实际上,将绑定称为“更改”上下文是不正确的。它的作用是将一个函数转换为另一个函数,该函数使用特定的上下文调用第一个函数。
可以通过多种方式绑定函数。例如,我可以自己绑定它:
function bind(fn,ctxt){
return function(){
fn.apply(ctxt,arguments);
};
}
或者,我可以将它与Function.prototype.bind绑定,或者用同样的东西绑定它,或者用下划线的_.bind绑定它。除了上下文之外,我还可以将它绑定到初始参数。在每种情况下,没有办法在没有实际执行函数的情况下判断发生了什么。
绑定只是将一个函数转换为另一个函数的众多方法之一。我也可以将函数转换为从现在开始执行一秒,或者执行两次。绑定没有什么魔力;它只是创建一个基于旧功能的新功能。在您可能能够检查的函数上没有设置名为[[bound_to]]的特殊变量(除非您使用自己的自定义bind实现,如另一个答案所示)。事后没有办法确定函数的转换方式。
我能想象到的最接近的是检查未绑定版本的可能绑定函数,看看它们是否相等。
function log_this(){console.log(this);}
var bound_func=log_this.bind(my_var);
console.log(log_this===bound_func); // FALSE
答案 1 :(得分:0)
可以做的是这样的事情:
function f(context, whatever) {
if(this !== context) {
//context has been changed
}
}
var y = f.bind(thingy);
y(otherThingy, something);
你也可以有一个自定义绑定功能,并且有一种这样的黑客攻击:
function bind(func, context) {
var newFunc = func.bind(context);
newFunc._this = context;
return newFunc;
}
function checkContext(func, context) {
return func._this !== context;
}
答案 2 :(得分:-1)
我认为对于那些喜欢JavaScirpt的人来说这是一个有趣的问题,我希望这是对你所寻找的回应:
var isContextSet = function (fn) {
var testThis = {}; //unique object for testing what is this inside fn
return fn.call(testThis) !== testThis;
}
我尝试在 fn :fn.call(testThis);
内“设置”这个,如果该函数返回对新创建的对象的引用( testThis )然后它没有绑定。我希望你明白:)
修改: 当 fn 重新调整时(如所示),这是有效的。否则你无法正确定义isContextSet。