摘要:的作用這段代碼可以在不同的上下文對象中重復使用函數和不用針對每個對象編寫不同版本的函數。顯然從字面意思來理解行不通執行時的確向函數對象添加了一個屬性。的綁定和函數聲明的位置沒有任何關系,只取決于函數調用的方式調用位置。
this的作用
function identify() { return this.name.toUpperCase() } function speak() { var greeting = "Hello" + identify.call(this) console.log(greeting) } var me = { name: "aa" } var you = { name: "bb" } identify.call(me) // AA identify.call(you) // BB speak.call(me) // HelloAA speak.call(you) // HelloBB
這段代碼可以在不同的上下文對象中重復使用函數identify()和speak()、不用針對每個對象編寫不同版本的函數。
如果不使用this,那就需要給identify()和speak()顯示傳入一個上下文對象
function identify(context) { return context.name.toUpperCase() } function speak(context) { var greeting = "Hello" + identify(context) console.log(greeting) } identify(you) // BB speak(me) //HelloAA
this提供了一種更優雅的方式來隱式”傳遞“一個對象引用,因此可以將API設計得更加簡潔并且易于復用,隨著使用的模式越來越復雜,顯示傳遞上下文對象會讓代碼變得越來越混亂,使用this則不會這樣
this是什么人們很容易把this理解成指向函數自身,從英文翻譯上理解似乎是對的,下面看個例子:
function foo(num) { console.log("foo" + num) this.count++ console.log(this === window) // true } foo.count = 0 var i; for (i = 0; i < 10; i++) { if (i > 5) { foo(i) } } console.log(foo.count) // 0
console.log語句產生了4條輸出,證明foo(...)確實被調用了4次,但是foo.count任然是0。顯然從字面意思來理解this行不通
執行foo.count = 0時的確向函數對象foo添加了一個屬性count。但是函數內部代碼this.count的this并不是指向那個函數對象,指向的是全局對象window
那么this到底是什么呢?
this是在運行時進行綁定的,并不是在編寫時綁定,它的上下文取決于函數調用時的各種條件。this的綁定和函數聲明的位置沒有任何關系,只取決于函數調用的方式(調用位置)。
當一個函數被調用時,會創建一個活動記錄(執行上下文)。這個記錄會包含函數在哪里被調用(調用棧)、函數的調用方式、傳入的參數等信息。this就是這個記錄的一個屬性,會在函數執行的過程中用到
首先介紹的是最常用的函數調用類型:獨立函數調用。可以把這條規則看作是無法應用其他規則時的默認規則,舉個例子:
function foo() { console.log(this.a) //2 } var a = 2 foo()
當調用foo()時,this.a被解析成了全局變量a,因為此時foo()是直接使用不帶任何修飾的函數引用進行調用的,只能用默認綁定,無法應用其他規則
但是當嚴格模式,不能將全局對象應用于默認綁定,this會綁定到undefined
另一條需要考慮的規則是調用位置是否有上下文對象。舉個例子
function foo() { console.log(this.a) } var obj = { a: 2, foo: foo } obj.foo() // 2
當foo()被調用時,它的前面加上了對obj的引用,當函數引用有上下文對象是,隱式綁定規則會把函數調用中this綁定到這個上下文對象。
對象屬性引用鏈中只有上一層或者說最后一層在調用位置中起作用。舉個例子
function foo() { console.log(this.a) } var obj2 = { a: 42, foo: foo } var obj1 = { a: 2, obj2: obj2 } obj1.obj2.foo() // 42隱式丟失
隱式綁定最常見的一個問題就是被隱式綁定的函數會丟失綁定對象,也就是會所它會應用默認綁定,從而把this綁定到全局對象或者undefine上,取決于是否嚴格模式,舉個例子:
function foo() { console.log(this.a) } var obj = { a: 2, foo: foo } var bar = obj.foo; var a = "global" bar() //相當于執行 foo() "global"
雖然bar是obj.foo的一個引用,但是實際上,它引用的是foo函數本身,因此此時的bar()其實是一個不帶任何修飾的函數調用,因此應用了默認綁定
顯示綁定javascript中提供的顯示綁定的方法就是大家都非常熟悉的call(...)、apply(...)和bind(...)方法,下面就簡單介紹一下它們的用法:
call的語法為:
fun.call(thisArg[, arg1[, arg2[, ...]]])
apply的語法為:
fun.apply(thisArg, [argsArray])
它們的第一個參數對象是一個對象,是個this準備的,接著在調用函數將其綁定到this。第二個參數 call 方法接受的是若干個參數列表,而apply接收的是一個包含多個參數的數組。
bind()方法創建一個新的函數, 當被調用時,將其this關鍵字設置為提供的值,在調用新函數時,在任何提供之前提供一個給定的參數序列。因此:bind 是創建一個新的函數,我們必須要手動去調用,舉個例子:
var a ={ fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.bind(a,1,2)() // 3new綁定
使用new來調用函數,會自動執行下面的操作
創建(或者說構造)一個全新的對象
這個新對象會被執行[[Prototype]]連接
這個對象會綁定到函數調用的this
如果函數沒有返回其他對象,那么new表達式中的函數調用會自動返回這個新對象
舉個例子:
function foo(a) { this.a = a } var bar = new foo(2) console.log(bar.a) // 2
使用new來調用foo(...)時,會構造一個新對象并把它綁定到foo(...)調用中的this上
綁定優先級函數是否在new中調用(new綁定)?如果是的話this綁定的是新創建的對象
函數是否通過call、apply、bind(顯示綁定)?如果是的話,this綁定是指定的對象
函數是否在某個上下文對象中調用(隱式綁定)?如果是的話,this綁定的是那個上下文對象
如果都不是,使用默認綁定,如果在嚴格模式下就綁定到undefined,否則綁定到全局對象
ES6中this指向ES6中的箭頭函數并不會使用上述的綁定規則,而是根據當前的詞法作用域來決定this,具體來說,箭頭函數會繼承外層函數調用的this綁定(無論this綁定到什么)舉個例子:
function Timer() { this.s1 = 0; this.s2 = 0; setInterval(() => this.s1++, 1000); setInterval(function () { this.s2++; }, 1000); } var timer = new Timer(); setTimeout(() => console.log("s1: ", timer.s1), 1100); // 1 setTimeout(() => console.log("s2: ", timer.s2), 1100); // 0
上例中s1的值是在箭頭函數中,會繼承Timer函數作用域中的this,而s2在普通函數中,根據之前的綁定綁定規則可以看出此時的this會執行默認的綁定規則綁定到全局對象上
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94254.html
摘要:作為構造函數調用中沒有類,但是可以從構造器中創建對象,并提供了運算符來進行調用該構造器。構造器的外表跟普通函數一樣,大部分的函數都可以當做構造器使用。如果構造函數顯式的返回一個對象,那么則會指向該對象。 this 的指向 this 是 js 中定義的關鍵字,它自動定義于每一個函數域內,但是它的指向卻讓人很迷惑。在實際應用中,this 的指向大致可以分為以下四種情況。 1.作為普通函數調...
摘要:再來看一個小的示例淘寶騰訊淘寶為什么輸出的依然是淘寶呢調用的是對象中的方法,方法里面有一個定時器,而定時器的一個參數是這里的指的就是的對象,然后方法里面有調用了,但是定時器中的指的是對象,所以最終調用的是對象中。 1.看前熱身 看一段代碼 var name = javascript; var obj = { name:js, foo:f...
摘要:語法參數這個對象將替代類里的對象可選在函數運行時使用的值。如果該參數的值為或,則表示不需要傳入任何參數。更簡單的講就是將和傳入函數執行。 學了那么久前端,對apply、call這兩個函數的用法,還不是很掌握。今天看了很多網上的文章,我總結和歸納下用法。 Function.prototype.apply() apply() 方法調用一個具有給定this值的函數,以及作為一個數組(或類似數...
摘要:但是有一個總的原則,那就是指的是,調用函數的那個對象使用主要分四種情況,討論下指針的用法和注意事項一純粹的函數調用這是函數的最通常用法,屬于全局性調用,因此就代表全局對象。 this是Javascript語言的一個關鍵字它代表函數運行時,自動生成的一個內部對象,只能在函數內部使用,隨著函數使用場合的不同,this的值會發生變化。但是有一個總的原則,那就是this指的是,調用函數的那個對...
摘要:但是有一個總的原則,那就是指的是,調用函數的那個對象使用主要分四種情況,討論下指針的用法和注意事項一純粹的函數調用這是函數的最通常用法,屬于全局性調用,因此就代表全局對象。 this是Javascript語言的一個關鍵字它代表函數運行時,自動生成的一個內部對象,只能在函數內部使用,隨著函數使用場合的不同,this的值會發生變化。但是有一個總的原則,那就是this指的是,調用函數的那個對...
閱讀 4983·2021-11-25 09:43
閱讀 1685·2021-10-27 14:18
閱讀 1057·2021-09-22 16:03
閱讀 1349·2019-08-30 13:19
閱讀 1572·2019-08-30 11:15
閱讀 1645·2019-08-26 14:04
閱讀 3124·2019-08-23 18:40
閱讀 1166·2019-08-23 18:17