javascriptvar foo={ x:3, exe:function(){ console.log(this); return this.x; } }
为什么
javascriptvar a = foo.exe; a();//undefined NO.1 (foo.exe=foo.exe)()//undefined NO.2
而
javascript(foo.exe)() //3 NO.3 foo.exe() //3 NO.4
特别是 NO.3 这种情况,小括号起到了什么作用?为什么 this 仍然指向这个对象?而 NO.2 和 NO.1 则指向了 window?
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
簡而言之,如果調用函數的表達式的結果(未經求值)是屬性引用,則 this 是屬性引用所在的對象,如果之前已經求值過了,則不再是屬性引用從而導致 this 成爲全局對象。
小括號運算符並不會導致表達式被求值,所以只影響解析時的優先級,不影響結果。
關於表達式,什麼是表達式?先看什麼是語句。
注意其中 ExpressionStatement。
也就是說,除了上面列出的情況,以及 {, function 開頭的情況,都是表達式構成語句。
foo是表達式,foo.bar是表達式,foo.bar()也是表達式。而
foo.bar();是一個語句,完全由表達式構成的語句。是一種語法糖。
函數調用其實就是:
而
http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.3 當中說 Function Calls:
也就是說,如果 MemberExpression 是一個 PropertyReference,就將 this 設置成訪問的對象。
所以,
以及
當中的 MemberExpression 都不是 PropertyReference,因此 this 默認是全局對象(直接訪問 a 是一個值,通過包含
=的表達式(屬於 AssignmentExpression)返回的也是值)。因爲賦值操作對表達式進行了 GetValue,所以不再是一個 PropertyReference。
小括號如果是表達式的一部分,那麼相當於:
當中的
( Expression )直接返回其中表達式(相當於小括號被無視,只起到改變優先級的功能)。
而取最後結果在函數調用時纔進行,所以仍舊可以屬於 PropertyReference
由於 Grouping Operator 並不會進行 GetValue 操作,
所以:
等價於:
前两种情况是一样的,相当于返回了这个函数。括号只是用来表示优先级的,而第二个和第三个的区别是第二个是一个表达式,有返回的。拆开来就是
函数的
this只和运行时的上下文有关,和声明定义时的上下文无关。此时a变量的上下文就是window所以this.x自然是undefined。第三种和第四种的情况是一样的,那个括号加上和没加都一样,具体就不多表了,不懂的话再提出来吧。
最后,SF 上关于
this的问题非常多,你提出的这个也有相关的问题,可以搜索学习一下。