成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JS中的this詳解

Mike617 / 2461人閱讀

摘要:實(shí)際上并不存在什么構(gòu)造函數(shù),只存在對(duì)于函數(shù)的構(gòu)造調(diào)用發(fā)生構(gòu)造函數(shù)的調(diào)用時(shí),會(huì)自動(dòng)執(zhí)行下邊的操作創(chuàng)建一個(gè)全新的對(duì)象。說明綁定的優(yōu)先級(jí)高于硬綁定。

原文閱讀

??js中的this是很容易讓人覺得困惑的地方,這篇文章打算說一下this綁定的幾種情況,相信可以解決大部分關(guān)于this的疑惑。

this是在運(yùn)行的時(shí)候綁定的,不是在編寫的時(shí)候綁定的,函數(shù)調(diào)用的方式不同,就可能使this所綁定的對(duì)象不同。

1.幾種綁定規(guī)則

??函數(shù)調(diào)用的位置對(duì)this的指向有著很大的影響,但卻不是完全取決于它。下面是幾種this的綁定規(guī)則:

1.1.默認(rèn)綁定

??默認(rèn)規(guī)則的意思就是在一般情況下,如果沒有別的規(guī)則出現(xiàn),就將this綁定到全局對(duì)象上,我們看如下代碼:

function foo() {
    var a = 3;
    console.log( this.a );
}
var a = 2;
foo();                        //2

??這段代碼中,this是被默認(rèn)綁定到了全局對(duì)象上,所以this.a得到的是2。我們?nèi)绾闻袛噙@里應(yīng)用了默認(rèn)綁定呢?foo在調(diào)用的時(shí)候直接使用不帶任何修飾的函數(shù)引用,只能使用默認(rèn)綁定。有人會(huì)誤認(rèn)為結(jié)果是3this常有的幾種錯(cuò)誤理解之一就是認(rèn)為this指向當(dāng)前函數(shù)的詞法作用域,this與詞法作用域以及作用域?qū)ο笫峭耆煌臇|西,作用域?qū)ο笫窃谝鎯?nèi)部的,js代碼是無法訪問的。還有本文我們不討論嚴(yán)格模式下的情況,嚴(yán)格模式這里的this會(huì)綁定到undefined

1.2.隱式綁定

??如果在調(diào)用位置有上下文對(duì)象,說簡(jiǎn)單點(diǎn)就是這個(gè)函數(shù)調(diào)用時(shí)是用一個(gè)對(duì)象.出來的。就像下邊這樣,它就遵循隱式綁定:

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2,
    foo: foo
}
var a = "opps, gloabl";                //全局對(duì)象的屬性
obj.foo();                    //2
var bar = obj.foo;
bar();                        //"opps, gloabl"

??第9行代碼,就是函數(shù)在調(diào)用的時(shí)候,是用前邊的對(duì)象加上.操作符調(diào)用出來的,此時(shí)就用到了隱式綁定規(guī)則,隱式綁定規(guī)則會(huì)將函數(shù)調(diào)用中的this綁定到這個(gè)上下文對(duì)象,此時(shí)的this.aobj.a是一樣的。
??而隱式綁定會(huì)出現(xiàn)一個(gè)問題,就是隱式丟失,上邊的第10行代碼,是新建一個(gè)foo函數(shù)的引用,即bar,在最后一行調(diào)用的時(shí)候,這個(gè)函數(shù)不具有上下文對(duì)象,此時(shí)采用默認(rèn)綁定規(guī)則,得到的結(jié)果自然是opps, gloabl;
??綁定丟失也會(huì)發(fā)生在函數(shù)作為參數(shù)傳遞的情況下,即傳入回調(diào)函數(shù)時(shí),因?yàn)閰?shù)傳遞就是一種隱式賦值,看如下代碼:

function foo() {
    console.log( this.a );
}
function doFoo(fn) {
    fn();            //在此處調(diào)用,參數(shù)傳遞是隱式賦值,丟失this綁定
}
var obj = {
    a: 2,
    foo: foo
};
var a = "opps, global";
doFoo( obj.foo );        //看似是隱式綁定,輸出opps, global

??javascript環(huán)境中內(nèi)置的函數(shù),在具有接受一個(gè)函數(shù)作為參數(shù)的功能的時(shí)候,也會(huì)發(fā)生像上邊這種狀況。例如setTimeout函數(shù)的實(shí)現(xiàn)就類似于下邊的偽代碼:

function setTimeout(fn, delay) {
    //等待delay毫秒
    fn();//在此處調(diào)用
}

??所以回調(diào)函數(shù)丟失this綁定是非常常見的,后邊我們?cè)倏慈绾瓮ㄟ^固定this來修復(fù)這個(gè)問題。

1.3.顯式綁定

??在此之前,相信你已經(jīng)用過很多次applycall函數(shù)了,使用這兩個(gè)函數(shù)可以直接為你要執(zhí)行的函數(shù)指定this,所以這種方式稱為顯式綁定。

function foo() {        //顯式綁定this,這種方式依然無法解決綁定丟失的問題
    console.log( this.a );
}
var obj = {
    a: 2
};
foo.call( obj );        //2

??通過像上邊這樣調(diào)用,我們可以將foothis強(qiáng)制綁定到obj上。如果給call傳入的是一個(gè)基本類型數(shù)據(jù),這個(gè)基本類型數(shù)據(jù)將會(huì)被轉(zhuǎn)換成對(duì)應(yīng)的基本包裝類型。不過這種方式依然無法解決上邊的丟失綁定問題。

1.3.1.硬綁定

??為了解決這個(gè)問題,我們可以寫像下邊這樣的代碼:

function foo() {
    console.log( this.a );
}
var obj = {
    a: 2
};
var bar = function() {         //創(chuàng)建一個(gè)包裹函數(shù),以確保obj的綁定
    foo.call( obj );
};
bar();                       //2
setTimeout( bar, 100 );           //2
bar.call( window );           //2

??上邊這樣的函數(shù)確實(shí)解決了綁定丟失的問題,每次調(diào)用bar就可以確保obj的綁定,不過還不能為函數(shù)傳參,而且這種方法復(fù)用率低,所以又出現(xiàn)了這樣的輔助綁定函數(shù):

function foo(something) {
    console.log( this.a, something );
    return this.a + something;
}
function bind(fn, obj) {        //輔助綁定函數(shù)
    return function() {
        return fn.apply( obj, arguments );
    };
}
var obj = {
    a: 2
};
var bar = bind( foo, obj );
var b = bar(3);
console.log(b);

??因?yàn)檫@種模式很常用,所以ES5內(nèi)置了這個(gè)方法,就是bind,bind(...)返回一個(gè)硬編碼的新函數(shù),將你指定的對(duì)象綁定到調(diào)用它的函數(shù)的this上。

function foo(something) {
    console.log( this.a, something );
    return this.a + something;
}
var obj = {
    a: 2
};
var bar = foo.bind( obj );    //bind返回一個(gè)綁定到obj上的新函數(shù)
var b = bar(3);
console.log(b);
var a = "window"s a";
foo("!");                       //對(duì)原來的函數(shù)不產(chǎn)生影響
1.3.2.API調(diào)用參數(shù)指定this

??許多第三方庫(kù)里的函數(shù),以及許多語言內(nèi)置的函數(shù),都提供了一個(gè)可選的參數(shù)用來指定函數(shù)執(zhí)行的this

function foo(el) {
    console.log( el, this.id );
}
var obj = {
    id: "awesome"
};
[1, 2, 3].forEach( foo, obj );   //forEach的第二個(gè)參數(shù)就是用來設(shè)置this
1.4.new綁定

js中的所謂的構(gòu)造函數(shù),其實(shí)和一般的普通函數(shù)沒有什么區(qū)別,并不具有特殊性,它們只是被new操作符調(diào)用的普通函數(shù)而已。實(shí)際上并不存在什么構(gòu)造函數(shù),只存在對(duì)于函數(shù)的構(gòu)造調(diào)用

發(fā)生構(gòu)造函數(shù)的調(diào)用時(shí),會(huì)自動(dòng)執(zhí)行下邊的操作:

創(chuàng)建一個(gè)全新的對(duì)象。

這個(gè)對(duì)象會(huì)被執(zhí)行[[Prototype]]連接。

這個(gè)新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this。

執(zhí)行這個(gè)函數(shù)里的代碼。

如果函數(shù)沒有返回其他對(duì)象,則自動(dòng)返回這個(gè)新對(duì)象。

這個(gè)在執(zhí)行new操作的時(shí)候?qū)?b>this的綁定就叫做new綁定。

function fun() {
  this.a = 1;
  this.b = 2;
}
var instance = new fun();
console.log(instance.a);
1.5.箭頭函數(shù)的this

??ES6中的箭頭函數(shù)是無法使用以上幾種規(guī)則的,它是根據(jù)外層的作用域來決定this,即取決于外層的函數(shù)作用域或全局作用域,而且箭頭函數(shù)的綁定無法修改,即使是new綁定也不可以。

function foo() {
    return (a) => {
        console.log( this.a );
    }
}
var obj1 = {
    a: 2
};
var obj2 = {
    a: 3
};
var bar = foo.apply(obj1);
bar.apply(obj2);        //2
2.綁定規(guī)則的優(yōu)先級(jí)

??前邊我們已經(jīng)說了this的幾種綁定規(guī)則,當(dāng)函數(shù)調(diào)用的位置可以使用多條綁定規(guī)則的時(shí)候,我們就需要確定這幾種規(guī)則的優(yōu)先級(jí)。

function foo() {
    console.log( this.a );
}
var obj1 = {
    a: 2,
    foo: foo
};
var obj2 = {
    a: 3,
    foo: foo
}
obj1.foo();        //2
obj2.foo();        //3
obj1.foo.call( obj2 );    //3
obj2.foo.call( obj1 );    //2

??從上邊的代碼可以看出來,顯式綁定的優(yōu)先級(jí)要高于隱式綁定,下邊再看看顯式綁定和new綁定的優(yōu)先級(jí):

function foo(something) {
    this.a = something;
}
var obj1 = {};
var bar = foo.bind( obj1 );
bar(2);
console.log( obj1.a );    //2
var baz = new bar(3);
console.log( obj1.a );    //2
console.log( baz.a );    //3

??仔細(xì)看這段代碼,barfoo綁定到obj1上返回的一個(gè)函數(shù),對(duì)這個(gè)函數(shù)進(jìn)行new操作,并傳入新的a值,發(fā)現(xiàn)改變的是新對(duì)象baz的屬性,和obj1已經(jīng)脫離關(guān)系。說明new綁定的優(yōu)先級(jí)高于硬綁定。

??綜上所述,我們?cè)谟龅?b>this時(shí),如果不是箭頭函數(shù),就可以以這種順序判斷它的指向:

如果函數(shù)在new中調(diào)用,綁定到新建的對(duì)象。

函數(shù)通過callapply或者硬綁定調(diào)用,this綁定到指定的對(duì)象上。

函數(shù)在某個(gè)上下文對(duì)象中調(diào)用,綁定到這個(gè)上下文對(duì)象上。

采用默認(rèn)綁定規(guī)則。

??以上就是這篇博客的所有內(nèi)容了,如果有什么理解的不對(duì)的地方歡迎討論,這里是我的博客以及github,歡迎來訪。

參考書籍:《你不知道的JavaScript(上卷)》

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/88324.html

相關(guān)文章

  • JavaScript深入淺出

    摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點(diǎn)提及,但是只要善于運(yùn)用,其實(shí)基于原型的繼承模型比傳統(tǒng)的類繼承還要強(qiáng)大。中文指南基本操作指南二繼續(xù)熟悉的幾對(duì)方法,包括,,。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。 怎樣使用 this 因?yàn)楸救藢儆趥吻岸?,因此文中只看懂?8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...

    blair 評(píng)論0 收藏0
  • 詳解js和jquery里的this關(guān)鍵字

    摘要:出于這個(gè)原因,該函數(shù)返回的,所以在這里指的是,所以返回的是第一個(gè)說明關(guān)鍵字通常在對(duì)象的構(gòu)造函數(shù)中使用,用來引用對(duì)象。重寫無法重寫,因?yàn)樗且粋€(gè)關(guān)鍵字。結(jié)論,表示當(dāng)前的上下文對(duì)象是一個(gè)對(duì)象,可以調(diào)用對(duì)象所擁有的屬性,方法。 在《javaScript語言精粹》這本書中,把 this 出現(xiàn)的場(chǎng)景分為四類,簡(jiǎn)單的說就是: 有對(duì)象就指向調(diào)用對(duì)象 沒調(diào)用對(duì)象就指向全局對(duì)象 用new構(gòu)造就指向新對(duì)...

    LoftySoul 評(píng)論0 收藏0
  • js 中的 call / apply 方法詳解和引用類型的繼承

    摘要:也就是說當(dāng)使用后,當(dāng)前執(zhí)行上下文中的對(duì)象已被替換為,后續(xù)執(zhí)行將以所持有的狀態(tài)屬性繼續(xù)執(zhí)行。借用的方法替換的實(shí)例去調(diào)用相應(yīng)的方法。實(shí)現(xiàn)引用類型的繼承其實(shí)沒有類這一概念,我們平時(shí)使用的等嚴(yán)格來說被稱作引用類型。 call 方法:object.method.call(targetObj[, argv1, argv2, .....]) apply 方法:object.method.apply(...

    cod7ce 評(píng)論0 收藏0
  • JavaScript之this對(duì)象詳解

    摘要:再來看一個(gè)小的示例淘寶騰訊淘寶為什么輸出的依然是淘寶呢調(diào)用的是對(duì)象中的方法,方法里面有一個(gè)定時(shí)器,而定時(shí)器的一個(gè)參數(shù)是這里的指的就是的對(duì)象,然后方法里面有調(diào)用了,但是定時(shí)器中的指的是對(duì)象,所以最終調(diào)用的是對(duì)象中。 1.看前熱身 看一段代碼 var name = javascript; var obj = { name:js, foo:f...

    Integ 評(píng)論0 收藏0
  • js事件詳解

    摘要:使用級(jí)方法指定的事件處理程序被認(rèn)為是元素的方法。用于立即停止事件在中的傳播,取消進(jìn)一步的事件捕獲或冒泡。捕獲事件目標(biāo)對(duì)象冒泡只有在事件處理程序執(zhí)行期間,對(duì)象才會(huì)存在,執(zhí)行完成后,對(duì)象就會(huì)被銷毀。 引用 事件是我認(rèn)為前端最特別的地方,這是唯一其他語言不一樣的地方,我們通過它與頁面進(jìn)行交互。 事件流 事件流描述的是從頁面中接收事件的順序。IE和網(wǎng)景團(tuán)隊(duì)提出流相反的事件流概念。IE事件流是事...

    AlienZHOU 評(píng)論0 收藏0
  • js事件詳解

    摘要:使用級(jí)方法指定的事件處理程序被認(rèn)為是元素的方法。用于立即停止事件在中的傳播,取消進(jìn)一步的事件捕獲或冒泡。捕獲事件目標(biāo)對(duì)象冒泡只有在事件處理程序執(zhí)行期間,對(duì)象才會(huì)存在,執(zhí)行完成后,對(duì)象就會(huì)被銷毀。 引用 事件是我認(rèn)為前端最特別的地方,這是唯一其他語言不一樣的地方,我們通過它與頁面進(jìn)行交互。 事件流 事件流描述的是從頁面中接收事件的順序。IE和網(wǎng)景團(tuán)隊(duì)提出流相反的事件流概念。IE事件流是事...

    xioqua 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<