Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么';Javascript不能正确绑定我的点表达式吗?_Javascript_Oop - Fatal编程技术网

为什么';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