一旦你了解了方法在幕后如何在 javascript 中工作,这实际上非常简单。
toUpperCase 是一种方法。这是一个对特定对象进行操作的函数……通常通过 this 变量。
Javascript 是一种原型语言......这意味着附加到对象的函数只是函数并且可以复制。幕后有一些工作可以确保在您调用方法时将this 设置为正确的东西,但这项工作仅在您将其作为方法调用时才会发生......就像obj.method() 形式一样。
换句话说:''.toUpperCase() 确保在您调用 this 时将其设置为字符串 ''。
当您将其称为toUpperCase() 时,this 未设置为任何特定内容(在这种情况下,不同的环境对this 执行不同的操作)
你的代码可以改写成这样:
var function_to_call;
if (true) {
function_to_call = ''.toLowerCase;
} else {
function_to_call = ''.toUpperCase;
}
function_to_call();
因为您的函数调用:function_to_call() 不在object.method() 语法中,所以将this 设置为正确对象的事情没有完成,并且您的函数调用在this 未设置为您想要的情况下执行.
正如其他人指出的那样,您可以使用func.call(thing_to_make_this) 或func.apply() 明确地将正确的内容附加到此。
我发现使用.bind() 更有帮助——在我看来,它的使用率极低。 function_name.bind(this_object) 为您提供了一个新函数,该函数将始终将 this 附加到正确的事物上:
// assuming function_to_call is set
function_that_works = function_to_call.bind(my_object)
function_that_works(); // equivalent to my_object.function_to_call()
这意味着您可以像普通函数一样传递从bind() 返回的函数,并且它将在您想要的对象上工作。这在回调中特别有用,因为您可以创建一个绑定到创建它的对象的匿名函数:
// this won't work because when this runs, 'this' doesn't mean what you think
setTimeout(function() { this.display_message('success'); }, 2000);
// this will work, because we have given setTimeout a pre-bound function.
setTimeout(function() { this.display_message('success'); }.bind(this), 2000);
TL;DR:您不能将方法作为函数调用并期望它工作,因为它不知道this 应该是什么。如果要使用该函数,则必须使用.call()、.apply() 或.bind() 以确保在函数执行时正确设置this。
希望对您有所帮助。