为什么Javascript没有正确绑定我的点表达式?

Sim*_*ang 28 javascript oop

我想知道点抽象方法(例如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上的字符串包装器.


amd*_*amd 7

因为这些方法适用于this上下文,并且在您的示例this未定义

使用方法覆盖变量的bind一种方法:

(true ? ''.toLowerCase : ''.toUpperCase).bind('Hello')();
Run Code Online (Sandbox Code Playgroud)

这将回来 hello

  • 只是`(true?''.toLowerCase:''.toUpperCase).call('Hello')`也可以. (3认同)

Jay*_*uri 7

一旦你了解方法如何在幕后的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在功能执行时正确设置.

希望有所帮助.

  • TL; DR:Javascript很疯狂. (4认同)
  • 由于理智主要基于人口规范,因此该陈述的真实性取决于你是在人口中还是在人口之外.我认为javascript是非常理智的,事实上非常酷和灵活的方式,而不是很多其他语言...但我不希望javascript只是javascript.如果您来自具有严格引用的语言和/或面向类的语言,则不能使用相同的准则.他们根本没有意义.这就像进入喷气式飞机的飞行员座位并询问换档位置和手套箱. (2认同)

归档时间:

查看次数:

2147 次

最近记录:

7 年,10 月 前