为什么';Javascript不能正确绑定我的点表达式吗?
我想知道点抽象方法(例如,为什么';Javascript不能正确绑定我的点表达式吗?,javascript,oop,Javascript,Oop,我想知道点抽象方法(例如,dog.bark)是在运行时绑定还是在编译时绑定。我的问题涉及以下代码,该代码引发错误: (true?“”.toLowerCase:“”.toUpperCase)( 相当于: String.prototype.toLowerCase.call() // or: String.prototype.toLowerCase.call(undefined) String.prototype.toLowerCase.call('') 但是, 相当于: String.prot
dog.bark
)是在运行时绑定还是在编译时绑定。我的问题涉及以下代码,该代码引发错误:
(true?“”.toLowerCase:“”.toUpperCase)(
相当于:
String.prototype.toLowerCase.call()
// or:
String.prototype.toLowerCase.call(undefined)
String.prototype.toLowerCase.call('')
但是,
相当于:
String.prototype.toLowerCase.call()
// or:
String.prototype.toLowerCase.call(undefined)
String.prototype.toLowerCase.call('')
在这两种情况下,call
的第一个参数被转换为对象,String.prototype.toLowerCase
中的this
将引用该对象
未定义的
无法转换为对象,但空字符串可以:
函数logThis(){console.log(this);}
logThis.call(“”)代码>因为当您执行(true?''.toLowerCase:'.toUpperCase)(
时,您没有调用绑定到字符串的函数。您只需在没有任何上下文的情况下调用函数
考虑以下示例:
var obj = {
objname: "objname",
getName: function() {
return this.objname;
}
}
当您使用obj.getName()
调用它时,它会正确返回值,但当您执行类似操作时:
var fn = obj.getName
fn() // returns undefined because `fn` is not bound to `obj`
因为这些方法适用于此
上下文,并且在您的示例中此
是未定义的
使用bind
方法覆盖此变量的一种方法:
(true ? ''.toLowerCase : ''.toUpperCase).bind('Hello')();
这将返回hello
在您的第一个示例中,toLowerCase
函数从其上下文(空字符串对象)分离,然后调用它。因为您没有将函数重新附加到它的上下文为未定义的任何内容上
存在此行为是为了通过混合插件实现代码重用:
var obj1={
名称:“obj1”,
getName:function(){返回this.name;}
}
变量obj2={
名称:“obj2”,
}
obj2.getName=obj1.getName//现在obj2具有具有正确上下文的getName方法
log(obj2.getName())
一旦您了解了javascript幕后方法的工作原理,这实际上非常简单
toUpperCase
是一种方法。这是一个作用于特定对象的函数。。。通常通过此
变量
Javascript是一种原型语言。。。这意味着附加到对象的函数只是函数,可以复制。在幕后有一些工作可以确保在调用方法时将设置为正确的值,但这项工作只有在将其作为方法调用时才会发生。。。如obj.method()
表单中所示
换句话说:'.toUpperCase()
确保调用时将this
设置为字符串'
当您将其称为toUpperCase()
时,此
没有设置为任何特定的值(在这种情况下,不同的环境使用此
执行不同的操作)
您的代码可以重写为:
var function_to_call;
if (true) {
function_to_call = ''.toLowerCase;
} else {
function_to_call = ''.toUpperCase;
}
function_to_call();
因为您的函数调用:function\u to\u call()
不在object.method()
语法中,所以将this
设置为正确对象的操作没有完成,并且您的函数调用执行时this
没有设置为您想要的值
正如其他人所指出的,您可以使用func.call(thing\u to\u make\u this)
或func.apply()
将正确的东西显式地附加到该函数
我发现使用.bind()
会更有帮助,在我看来,这一点使用得非常少function\u name.bind(this\u对象)
为您提供了一个新函数,该函数始终将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:你不能把一个方法作为函数调用,然后期望它工作,因为它不知道这个应该是什么。如果要使用该函数,必须使用.call()
、.apply()
或.bind()
,以确保在函数执行时正确设置
希望有帮助。当你做dog.bark()
,这个里面的bark
会指向dog
。但当您执行fn=dog.bark
时,您是在复制函数的引用。因此,在fn()
中,这个
将根据环境指向窗口
或未定义的
。。JavaScript不是一种编译语言。只有运行时。@alexisking谢谢,我一直在寻找一个合适的副本。我们没有比和更好的吗?肯定有一个问题,为什么JS方法不能像Python那样工作!我还发现,.Just(true?“”.toLowerCase:“”.toUpperCase).call('Hello')
也可以。@IlmariKaronen,true我想通过在这里使用bind
来说明我覆盖了this
变量tl;博士:Javascript是疯狂的。因为理智在很大程度上是基于人群中的规范,所以这种说法的真实性取决于你是在人群中还是在人群之外。我认为javascript是非常明智的,事实上非常酷和灵活,这是其他语言所不具备的。。。但我并不期望javascript是javascript以外的任何东西。如果您来自具有严格引用的语言和/或面向类的语言,则不能使用相同的准则。它们根本没有意义。这就像坐在飞机的驾驶座上,问变速箱和手套箱在哪里。我知道它很旧,但你第一次说“相当于”的地方是完全错误的。在第三级表达式中,'.toLowerCase
将不调用该函数。它只会检查String.prototype
中的toLowerCase
是否错误。所以这两个班轮的第一行应该是r