javascript - vue用法 - vue組件
為什麼Javascript不能正確綁定我的點表達式? (4)
因為當你這樣做(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`
這個問題在這裡已經有了答案:
- “this”是Javascript 4中 的全局對象的情況下的 答案
我想知道是否點抽象方法(如dog.bark
)綁定在運行時或在編譯時。 我的問題涉及下面的代碼,它會引發一個錯誤:
(true ? ''.toLowerCase : ''.toUpperCase)()
但是以下不是:
true ? ''.toLowerCase() : ''.toUpperCase()
為什麼我的字符串文字在第一個例子中沒有得到解決?
因為這些方法適用於this
上下文,在你的例子中, this
是不確定的
通過使用bind
方法覆蓋此變量的一種方法:
(true ? ''.toLowerCase : ''.toUpperCase).bind('Hello')();
這將返回hello
在第一個例子中,首先對括號中的表達式進行求值,這會導致對toLowerCase
或toUpperCase
的函數引用,然後對未定義的表達式([expression])()
的結果調用該函數。 這是非法的。
然而,在第二個例子中,在第三次比較評估期間,在空字符串上調用toLowerCase
或toUpperCase
,並將函數的返回值分配給左側操作數。 分配給未定義的不是非法的。
''[(true ? 'toLowerCase' : 'toUpperCase')]()
這實際上很簡單,一旦你得到如何在JavaScript的方法在幕後工作。
toUpperCase
是一種方法。 這是一個對特定對象進行操作的函數...通常通過this
變量。
Javascript是一個原型語言...意味著附加到對象的功能只是功能,可以復制。 在幕後有一些工作可以確保在你調用一個方法的時候this
設置是正確的,但是這個工作只有當你把它作為一個方法調用時才會發生......就像在obj.method()
窗體中一樣。
換句話說: ''.toUpperCase()
確保在你調用它時設置為字符串''
。
當你把它稱為toUpperCase()
this
並沒有被設置為特定的東西(在這種情況下,不同的環境會做不同的事情)
你的代碼可以重寫為:
var function_to_call;
if (true) {
function_to_call = ''.toLowerCase;
} else {
function_to_call = ''.toUpperCase;
}
function_to_call();
因為你的函數調用: function_to_call()
不在object.method()
語法中,所以把它設置成正確的對象的事情沒有完成,你的函數調用執行時沒有設置你想要的。
正如其他人已經指出的,你可以使用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()
這意味著你可以傳遞你從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:你不能把一個方法作為一個函數來調用,並期望它能夠工作,因為它不知道應該是什麼。 如果你想使用這個函數,你必須使用.apply()
或.bind()
來確保在函數執行的時候this
設置是正確的。
希望有所幫助。