您好,登錄后才能下訂單哦!
小編給大家分享一下Javascript的this有什么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
在理解javascript的this之前,首先先了解一下作用域。
作用域分為兩種:
1、詞法作用域:引擎在當(dāng)前作用域或者嵌套的子作用域查找具有名稱標(biāo)識(shí)符的變量。(引擎如何查找和在哪查找。定義過程發(fā)生在代碼書寫階段)
2、動(dòng)態(tài)作用域:在運(yùn)行時(shí)被動(dòng)態(tài)確定的作用域。
詞法作用域和動(dòng)態(tài)作用域的區(qū)別是:詞法作用域是在寫代碼或定義時(shí)確定的;動(dòng)態(tài)作用域是在運(yùn)行時(shí)確定的。
this的綁定規(guī)則
this是在調(diào)用時(shí)被綁定,取決于函數(shù)的調(diào)用位置。由此可以知道,一般情況下(非嚴(yán)格模式下),this都會(huì)根據(jù)函數(shù)調(diào)用(調(diào)用棧)的上下文來綁定對(duì)象。
一、默認(rèn)綁定
默認(rèn)綁定:默認(rèn)綁定是指在非嚴(yán)格模式下,且沒有使用別的綁定規(guī)則時(shí),this根據(jù)函數(shù)調(diào)用(調(diào)用棧)的上下文來綁定對(duì)象(全局對(duì)象)。(嚴(yán)格模式下則綁定undefined)
舉個(gè)栗子:
function foo() { console.log(this.a); }; function bar() { var a = 3; foo(); } var a = 2; bar(); //調(diào)用棧在全局作用域,this綁定全局對(duì)象
運(yùn)行結(jié)果為: 2
//加上"use strict"運(yùn)行結(jié)果則會(huì)變成this is undefined
這里的函數(shù)調(diào)用時(shí),使用了默認(rèn)綁定,函數(shù)調(diào)用(調(diào)用棧)的上下文是全局作用域,因此this綁定了全局對(duì)象(global)。
eg2:
function foo() { console.log(this.a) }; var a = 2; (function() { "use strict" foo(); })();
運(yùn)行結(jié)果為: 2
這里需要注意:對(duì)于默認(rèn)綁定,決定this綁定對(duì)象的不是調(diào)用位置是否處于嚴(yán)格模式,而是函數(shù)體是否處于嚴(yán)格模式(函數(shù)體處于嚴(yán)格模式則this綁定undefined;否則this綁定全局對(duì)象)。另外:嚴(yán)格模式和非嚴(yán)格模式雖然有可能可以綁定,但是最好不混用。
間接引用一般也是會(huì)應(yīng)用默認(rèn)綁定規(guī)則。
function foo() { console.log(this.a); }; var a = 2; var o = { a: 3, foo: foo }; var p = { a: 4 }; o.foo(); //3 (p.foo = o.foo)(); //2
賦值表達(dá)式 p.foo = o.foo的返回值是直接引用目標(biāo)函數(shù)foo。
二、隱式綁定
隱式綁定:由上下文對(duì)象調(diào)用,綁定到上下文對(duì)象。
舉個(gè)栗子:
function foo() { console.log(this.a); }; var obj = { a: 2, foo: foo }; obj.foo(); //2 foo(); //undefined
這段代碼中,foo()被當(dāng)做引用屬性添加到obj對(duì)象中,obj調(diào)用這個(gè)引用屬性函數(shù)時(shí),會(huì)使用該引用屬性上下文,this會(huì)被綁定到obj對(duì)象。(這個(gè)函數(shù)嚴(yán)格來說不屬于obj對(duì)象,只是作為引用屬性)。屬于隱式綁定。
而下面foo()函數(shù)的直接執(zhí)行,并不是obj對(duì)象引用,所以上下文對(duì)象是全局對(duì)象。故this綁定了undefined。屬于默認(rèn)綁定。
對(duì)象引用鏈中只有上一層或者說最后一層在調(diào)用位置中起作用。
注意:
1.隱式綁定的函數(shù)會(huì)丟失綁定對(duì)象。此時(shí)它會(huì)應(yīng)用默認(rèn)綁定,將this綁定到全局對(duì)象或者undefined上,取決于是否是嚴(yán)格模式。
eg:
function foo() { console.log(this.a); }; var obj = { a: 2; foo: foo } var bar = obj.foo; var a = 'biubiubiu'; bar();
運(yùn)行結(jié)果:"biubiubiu"
解析:看似bar是obj.foo的一個(gè)引用,實(shí)際上bar是直接引用了函數(shù)foo,是一個(gè)單純的函數(shù)調(diào)用,故實(shí)為默認(rèn)綁定。
2.參數(shù)傳遞就是隱式賦值,因此傳入函數(shù)時(shí)也會(huì)被隱式賦值。
eg:
function foo() { console.log(this.a); }; var obj = { a: 2, foo: foo }; function bar(fn) { fn(); }; var a = "biubiubiu"; bar(obj.foo);
運(yùn)行結(jié)果: "biubiubiu"
解析:實(shí)際上參數(shù)也是隱式賦值,但是參數(shù)傳入函數(shù)中,并在函數(shù)中執(zhí)行。此時(shí)也是直接引用了函數(shù)foo,因此也是單純的函數(shù)調(diào)用,采用了默認(rèn)綁定。
3.把函數(shù)傳入語言內(nèi)置函數(shù)。(與上面情況基本相似,將自己聲明函數(shù)改成語言內(nèi)置函數(shù))回調(diào)函數(shù)丟失this的情況比較常見,況且還有調(diào)用回調(diào)函數(shù)的函數(shù)可能還會(huì)修改this。
三、顯式綁定
顯式綁定:直接將this綁定到指定對(duì)象上。Javascript中絕大多數(shù)函數(shù)和自己所創(chuàng)建的函數(shù)都可以使用這兩種顯式綁定的方法。
1、.call()
2、.apply()
這兩種綁定方法,第一個(gè)參數(shù)是this綁定的對(duì)象。(如果傳入的參數(shù)是原始值(字符串類型、布爾類型、數(shù)字類型),這個(gè)原始值就會(huì)被轉(zhuǎn)成對(duì)象形式(new String、new Boolean、new Number)這個(gè)稱為:裝箱)
舉個(gè)栗子:
function foo() { console.log(this.a); }; var obj = { a: 2 }; foo.call(obj);
運(yùn)行結(jié)果: 2
然鵝,顯示綁定并不能解決綁定丟失的問題。這個(gè)時(shí)候來了一位新朋友 -- 硬綁定(bind)。
3、.bind() (硬綁定是常見場(chǎng)景,故es5提供了該內(nèi)置方法 Function.prototype.bind。)
bind()會(huì)返回一個(gè)新編碼函數(shù),把this綁定在指定參數(shù)上,并調(diào)用函數(shù)。
舉個(gè)栗子:
function foo(e) { console.log(this.a + e); return this.a + e; }; var obj = { a: 2 } var bar = foo.bind(obj); //新編碼函數(shù) var b = bar(3); // 2 3 console.log(b); // 5
bind()還有一個(gè)功能:將除了第一個(gè)用于綁定this的參數(shù)之外的其他參數(shù)傳給下層的函數(shù)(部分應(yīng)用,是“柯里化”的一種)。
這里涉及到一個(gè)概念:把null或者undefined作為this的綁定對(duì)象傳入call、apply、bind,這些值在調(diào)用的時(shí)候會(huì)被忽略,實(shí)際應(yīng)用默認(rèn)綁定規(guī)則。
應(yīng)用場(chǎng)景:
1、使用apply()展開一個(gè)數(shù)組,并作為參數(shù)傳遞給一個(gè)函數(shù)。
2、bind()對(duì)參數(shù)進(jìn)行柯里化(預(yù)先設(shè)置一些參數(shù))。
舉個(gè)栗子:
function foo(a,b) { console.log("a:" + a + ",b:" + b); }; //數(shù)組“展開”成參數(shù) foo.apply(null,[2,3]); //a:2,b:3 //bind()柯里化 var bar = foo.bind(null,2); bar(3); //a:2,b:3
解析:傳入一個(gè)參數(shù)作為this綁定對(duì)象,如果不傳則使用占位符(null),此時(shí)會(huì)使用默認(rèn)綁定規(guī)則。
上面這個(gè)例子可能會(huì)產(chǎn)生一定的副作用,如果需要運(yùn)用這種場(chǎng)景并且更加安全。可以創(chuàng)建一個(gè)空對(duì)象(可以用任意喜歡的名字來命名)。
var ? = Object.create(null); //上面這個(gè)例子就可以改寫為: foo.apply(?,[2,3]); //a:2,b:3 var bar = foo.bind(?,2); bar(3); //a:2,b:3
注意:硬綁定之后不能使用隱式綁定和顯式綁定對(duì)this進(jìn)行修改
在這里介紹一種軟綁定的方法softBind(),檢查this綁定到全局對(duì)象或者undefined后,綁定this到指定的默認(rèn)對(duì)象。綁定后效果和硬綁定一樣,但是保留隱式綁定或者顯式綁定修改this的能力。
四、new綁定
Javascript中的new機(jī)制與面向類語言的完全不同。在Javascript中,構(gòu)造函數(shù)只是一些使用new操作符時(shí)被調(diào)用的函數(shù),不屬于一個(gè)類,也不會(huì)實(shí)例化一個(gè)類。稱為對(duì)函數(shù)的“構(gòu)造調(diào)用”。
舉個(gè)栗子:
function foo(a) { this.a = a; } var bar = new foo(2); console.log(bar.a); //2
使用new的過程會(huì)創(chuàng)建一個(gè)全新的對(duì)象,this會(huì)綁定這個(gè)新對(duì)象。如果函數(shù)沒有返回其他對(duì)象,則new表達(dá)式函數(shù)調(diào)用會(huì)返回該新對(duì)象。(這個(gè)新對(duì)象會(huì)連接prototype)
四種綁定規(guī)則的優(yōu)先級(jí)為:new>顯式>隱式>默認(rèn)
箭頭函數(shù)
箭頭函數(shù)是根據(jù)外層作用域(函數(shù)或全局)來決定this。(詞法作用域取代this機(jī)制)
箭頭函數(shù)this會(huì)綁定調(diào)用時(shí)的對(duì)象,且箭頭函數(shù)的綁定無法修改(new也不行)。
其實(shí)可以理解為,箭頭函數(shù)的this在詞法上繼承的是它所在的作用域(函數(shù)或全局)的this,而它繼承的函數(shù)作用域的this綁定的是在該函數(shù)調(diào)用上下文對(duì)象,所以箭頭函數(shù)的this間接的綁定在調(diào)用上下文對(duì)象。
簡(jiǎn)述: 箭頭函數(shù)this(綁定作用域this)-- 作用域this(綁定在調(diào)用上下文對(duì)象)。
故:箭頭函數(shù)this == 調(diào)用的上下文對(duì)象
舉個(gè)栗子:
function foo() { setTimeout(function() { //這里的this在詞法上繼承自foo() console.log(this.a); },100); }; var obj = { a: 2 }; foo.call(obj); //2
其實(shí)這個(gè)栗子也等價(jià)于:
function foo() { var that = this; //lexical capture of this setTimeout(function() { console.log(self.a) },100); } ...與上面一樣
所以,有兩種風(fēng)格:this風(fēng)格(四種規(guī)則)和詞法作用域風(fēng)格(that = this和箭頭函數(shù))可供使用。使用時(shí)盡量避免混用,否則會(huì)造成難以維護(hù)的后果。
以上是“Javascript的this有什么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。