我想知道点抽象方法(例如dog.bark)是在运行时还是在编译时绑定.我的问题涉及以下代码,它会引发错误:
(true ? ''.toLowerCase : ''.toUpperCase)()Run Code Online (Sandbox Code Playgroud)
但以下不是:
true ? ''.toLowerCase() : ''.toUpperCase()Run Code Online (Sandbox Code Playgroud)
为什么我的字符串文字''在第一个例子中没有得到解决?
Pet*_*der 21
(true ? ''.toLowerCase : ''.toUpperCase)()
Run Code Online (Sandbox Code Playgroud)
相当于:
String.prototype.toLowerCase.call()
// or:
String.prototype.toLowerCase.call(undefined)
Run Code Online (Sandbox Code Playgroud)
然而,
true ? ''.toLowerCase() : ''.toUpperCase()
Run Code Online (Sandbox Code Playgroud)
相当于:
String.prototype.toLowerCase.call('')
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,第一个参数call都转换为一个对象,thisin String.prototype.toLowerCase将引用该对象.
undefined 无法转换为对象,但空字符串可以:
function logThis () { console.log(this); }
logThis.call('');Run Code Online (Sandbox Code Playgroud)
SO片段控制台只显示{},但它实际上与您相同new String('').阅读MDN上的字符串包装器.
因为这些方法适用于this上下文,并且在您的示例this中未定义
使用方法覆盖此变量的bind一种方法:
(true ? ''.toLowerCase : ''.toUpperCase).bind('Hello')();
Run Code Online (Sandbox Code Playgroud)
这将回来 hello
一旦你了解方法如何在幕后的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();
Run Code Online (Sandbox Code Playgroud)
因为你的函数调用: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()
Run Code Online (Sandbox Code Playgroud)
这意味着你可以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);
Run Code Online (Sandbox Code Playgroud)
TL; DR:您不能将方法作为函数调用并期望它可以工作,因为它不知道this应该是什么.如果要使用该功能,则必须使用.call(),.apply()或.bind()确保this在功能执行时正确设置.
希望有所帮助.
| 归档时间: |
|
| 查看次数: |
2147 次 |
| 最近记录: |