成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript || this

ShowerSun / 2714人閱讀

摘要:是中的一個屬性解析函數(shù)調(diào)用位置函數(shù)在程序代碼中被調(diào)用的位置,清楚調(diào)用位置才能明確的指向確定函數(shù)的調(diào)用位置最關(guān)鍵是分析調(diào)用棧為達(dá)到當(dāng)前指向位置所調(diào)用的所有函數(shù)。

關(guān)于this

this是JavaScript的一個關(guān)鍵字,自動定義在所有函數(shù)中,難點在于this的指向。

this的指向在函數(shù)調(diào)用時進(jìn)行綁定,它的context取決于函數(shù)調(diào)用時的各種條件,與函數(shù)定義位置無關(guān)

1 this的作用

this可以使不同的context對象重復(fù)使用已經(jīng)存在、聲明的函數(shù),無需針對每個對象編寫不同版本的函數(shù)

function identify() {
    return this.name.toUpperCase();
}
function speak() {
    var greeting = "Hello, i"m " + identify.call( this );    
    console.log( greeting );
}

var me = {name: "Kyle"};
var you = {name: "Reader"};

identify.call( me );         // KYLE
identify.call( you );       // READER

speak.call( me );              // "Hello, i"m KYLE"
speak.call( you );              // "Hello, i"m READER"
2 誤解

this并不是指向函數(shù)本身

在任何情況下,this都不指向函數(shù)的詞法作用域

3 this是什么?

this是在函數(shù)被調(diào)用時發(fā)生綁定,其指向取決于函數(shù)調(diào)用的位置。

當(dāng)一個函數(shù)被調(diào)用是,會創(chuàng)建一個執(zhí)行上下文(context)。其中包含函數(shù)的調(diào)用位置(調(diào)用棧)、函數(shù)的調(diào)用方式和傳入的參數(shù)等信息。thiscontext中的一個屬性

4 this解析 4.1 函數(shù)調(diào)用位置

函數(shù)在程序代碼中被調(diào)用的位置,清楚調(diào)用位置才能明確this的指向

確定函數(shù)的調(diào)用位置:最關(guān)鍵是分析調(diào)用棧(為達(dá)到當(dāng)前指向位置所調(diào)用的所有函數(shù))。分析調(diào)用棧,可以得出真正的調(diào)用位置

function baz() {
    // 當(dāng)前調(diào)用棧是:baz
    // 所以當(dāng)前調(diào)用位置時全局作用域

    console.log("baz");
    bar(); // <-- bar的調(diào)用位置
}

function bar() {
    // 當(dāng)前調(diào)用棧是:baz --> bar
    // bar的調(diào)用位置在baz中

    console.log("bar");
    foo(); // <-- bar的調(diào)用位置
}

function foo() {
    // 當(dāng)前調(diào)用棧是:baz --> bar --> foo
    // foo的調(diào)用位置在bar中

    console.log("foo");
}
baz();   //  --> baz的調(diào)用位置
4.2 this的綁定規(guī)則

在分析清楚調(diào)用位置后,根據(jù)this綁定的四條規(guī)則決定綁定對象。四條規(guī)則分別對應(yīng)四種不同的函數(shù)調(diào)用方式

總共有四條綁定規(guī)則,其優(yōu)先級是:默認(rèn)綁定 < 隱式綁定 < 顯式綁定 < new綁定

默認(rèn)綁定:作為獨立調(diào)用的函數(shù)

隱式綁定:作為對象的方法調(diào)用的函數(shù)

顯式綁定(硬綁定):使用call()、apply()bind()方法,強制將對象綁定到函數(shù)的this

new綁定:

4.2.1 默認(rèn)綁定

默認(rèn)綁定指將函數(shù)作為獨立的函數(shù)來調(diào)用,默認(rèn)綁定將this綁定到全局對象。

分析隱式綁定時,一個對象內(nèi)部包含一個指向函數(shù)的屬性,并且通過對象的屬性間接引用函數(shù),將this間接綁定到該對象上

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

a在全局作用域中聲明,是全局對象的一個屬性;

foo()使用不帶任何修飾的函數(shù)進(jìn)行調(diào)用,只能使用默認(rèn)綁定規(guī)則;此時,非嚴(yán)格模式下this指向全局對象,所有this.a被解析為全局變量a

在嚴(yán)格模式中,this不能綁定到全局對象,this只能綁定到undefined

function foo() {
    "use strict";
    console.log(this.a);
}
var a = 2;
foo();  // TypeError: this is undefined

4.2.2 隱式綁定

判斷函數(shù)的調(diào)用位置是否有上下文對象,隱式綁定將this綁定到調(diào)用方法的上下文對象上。

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2,
    foo: foo
};
obj.foo();  // 2   foo()的調(diào)用位置包含上下文對象obj,this隱式綁定到obj對象

對象屬性引用鏈中,只有最后一層會影響調(diào)用位置

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2,
    obj2: obj2
};

var obj2 = {
    a: 42,
    foo: foo

obj.obj2.foo();  // 42   實際是通過obj對象的obj2屬性對象來調(diào)用foo()函數(shù),this指向obj2

隱式丟失

被隱式綁定的函數(shù)會丟失綁定對象,然后應(yīng)用默認(rèn)綁定,非嚴(yán)格模式下將this綁定到全局對象。

隱式綁定丟失發(fā)生在將隱式綁定的函數(shù)賦值給另外的變量,通過改變了來調(diào)用函數(shù)

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2,
    foo: foo
};
var bar = obj.foo;   //  函數(shù)別名,傳遞引用
var  a = "global a";
bar();  // "global a",函數(shù)的調(diào)用位置,bar()其實是一個不帶任何修飾的函數(shù)調(diào)用,所以應(yīng)用默認(rèn)的綁定規(guī)則

在函數(shù)中將回調(diào)函數(shù)作為參數(shù)傳入時,參數(shù)傳遞是一種隱式賦值(傳遞引用),所以應(yīng)用默認(rèn)綁定規(guī)則

function foo() {
    console.log(this.a);
}
function doFoo(fn) {
    // fn是obj.foo函數(shù)本身的一個引用

    fn();   // fn的調(diào)用位置
}
var obj = {
    a: 2,
    foo: foo
};
var bar = obj.foo;   //  函數(shù)別名,傳遞引用
var  a = "global a";
doFoo(obj.foo);  // "global a",傳入的函數(shù)被隱式賦值,應(yīng)用默認(rèn)綁定規(guī)則

setTimeout(obj.foo, 100);   //"global a",使用語言本身的內(nèi)置函數(shù)時道理相同

4.2.3 顯式綁定

在JavaScript中,函數(shù)是對象,每個函數(shù)對象都定義有call()、apply()bind()方法,bind()在ES5中。

call()、apply()方法:

第一個方法是一個對象,將該對象綁定到this

可以直接指定綁定的對象,稱為顯示綁定

call()、apply()區(qū)別在于其他參數(shù)

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2,
    foo: foo
};
foo.call(obj);   // 2  通過foo.call(obj);,在調(diào)用foo()時強制將其this綁定到obj對象

顯式綁定仍然會有綁定丟失問題:可以使用顯示綁定的一個變形來解決這個問題;

硬綁定

創(chuàng)建一個函數(shù)bar(),在內(nèi)部調(diào)用foo.call(obj),強制將foothis綁定到obj對象上,無論怎樣調(diào)用bar()函數(shù),都會手動在obj對象上調(diào)用foo,因此foothis指向不會改變

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2,
    foo: foo
};
var bar = function() {
    foo.call(obj);   
}

bar();   //  2
setTimeout( bar, 100 ); // 2
// 硬綁定的bar不能再修改它的this指向
bar.call(window);   // 2

硬綁定的應(yīng)用場景

創(chuàng)建一個包裹函數(shù),傳入所有的參數(shù),并返回接收到的所有值

function foo(sth) {
    return this.a + sth;
}
var obj = {
    a: 2
};
var bar = function() {
    // 將arguments傳入需要調(diào)用的函數(shù)
    return foo.apply(obj, arguments);   
}

bar(3);   //  2 + 3 = 5

創(chuàng)建一個可以重復(fù)使用的函數(shù)

function foo(sth) {
    return this.a + sth;
}
var obj = {
    a: 2
};
// 簡單的輔助綁定函數(shù)
function bind(fn, obj) {
    return function() {
        return fn.apply(obj, arguments);
    }
}

var bar = bind(foo, obj);
bar(3);   //  2 + 3 = 5

硬綁定是一種非常常見的模式,ES5提供內(nèi)置Function.prototype.bind方法:返回一個硬綁定的新函數(shù),bind(obj)將參數(shù)obj設(shè)置為this的上下文,并調(diào)用原始函數(shù)。

function foo(sth) {
    return this.a + sth;
}
var obj = {
    a: 2
};

var bar = foo.bind(obj);
bar(3);   //  2 + 3 = 5

4.2.4 new綁定

JavaScript中的new機制與傳統(tǒng)面向?qū)ο笳Z言不同。JavaScript中構(gòu)造函數(shù)只是使用new操作符調(diào)用的函數(shù),使用new操作符調(diào)用函數(shù)時:

創(chuàng)建一個全新對象;

新對象被執(zhí)行__proto__鏈接

新創(chuàng)建的對象被綁定到函數(shù)調(diào)用時的this

如果函數(shù)沒有返回其他對象,new表達(dá)式中的函數(shù)調(diào)用自動返回新創(chuàng)建的對象

function foo(a) {
    this.a = a;
}

var bar = new foo(2);
console.log(bar.a);  // 2

4.3 優(yōu)先級

判斷this的指向:找到函數(shù)的調(diào)用位置,并根據(jù)優(yōu)先級判斷應(yīng)用的規(guī)則,默認(rèn)綁定的優(yōu)先級最低

顯示綁定的優(yōu)先級高于隱式綁定:在判斷時優(yōu)先考慮顯示綁定

function foo(a) {
    this.a = a;
}

var obj1 = {
    a: 2;
    foo: foo
};
var objb = {
    a: 4;
    foo: foo
};

obj1.foo();  // 2
obj2.foo();  // 4

obj1.foo.call(obj2);   // 4
obj2.foo.call(obj1);   // 2

new綁定的優(yōu)先級高于隱式綁定:

new綁定的優(yōu)先級的高于顯示綁定:

bar被硬綁定到obj1對象上,但是new bar(3)并未將obj1.a修改為4;

new bar(3)修改了調(diào)用bar()中的this,得到一個新對象

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

var baz = new bar(4);
console.log(obj1.a);  // 2
console.log(baz.a);  // 4

4.4 根據(jù)優(yōu)先級判斷函數(shù)調(diào)用位置應(yīng)用的規(guī)則

函數(shù)是否在new中調(diào)用?如果是,this綁定新創(chuàng)建的對象

函數(shù)是否通過call()apply()顯示綁定?或者bind()硬綁定?如果是,this指向綁定的對象。

函數(shù)是否在某個上下文對象中調(diào)用?如果是,this指向那個上下文對象

如果不是上述三種情況,使用默認(rèn)綁定。嚴(yán)格模式下綁定到undefined,非嚴(yán)格模式下綁定到全局對象

4.5 綁定例外 4.5.1 被忽略的this

nullundefined作為this的綁定對象傳入call()、apply()bind()方法,在調(diào)用時被忽略,實際應(yīng)用默認(rèn)綁定規(guī)則。

使用null來忽略this綁定可能產(chǎn)生副作用:安全的做法是傳入一個特殊對象,將this綁定到這個對象不會產(chǎn)生任何副作用。Object.create(null)。

5 this詞法

ES6中的箭頭函數(shù)不能使用上述4種規(guī)則,而是根據(jù)外層(函數(shù)或全局)作用域來絕對this。箭頭函數(shù)常用于回調(diào)函數(shù)中。

function foo() {
    // 返回一個箭頭函數(shù)
    return (a) => {
        // this繼承自foo()
        console.log(this.a);
    }
}
var obj = {
    a: 2
};

var obj2 = {
    a: 42
};

var bar = foo.call(obj1);  
bar.call(obj2);   // 2, 不是42

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86855.html

相關(guān)文章

  • JavaScript深入淺出

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

    blair 評論0 收藏0
  • javascript技術(shù)難點(三)之this、new、apply和call詳解

    摘要:第四點也要著重講下,記住構(gòu)造函數(shù)被操作,要讓正常作用最好不能在構(gòu)造函數(shù)里 4) this、new、call和apply的相關(guān)問題 講解this指針的原理是個很復(fù)雜的問題,如果我們從javascript里this的實現(xiàn)機制來說明this,很多朋友可能會越來越糊涂,因此本篇打算換一個思路從應(yīng)用的角度來講解this指針,從這個角度理解this指針更加有現(xiàn)實意義。 下面我們看看在ja...

    ghnor 評論0 收藏0
  • JavaScript進(jìn)階之’this

    摘要:所以相同點是,在全局范圍內(nèi),全局變量終究是屬于老大的。只生效一次引入了。只生效一次在箭頭函數(shù)中,與封閉詞法環(huán)境的保持一致。我通常把這些原始函數(shù)叫做構(gòu)造函數(shù)。在里面你可以嵌套函數(shù),也就是你可以在函數(shù)里面定義函數(shù)。 showImg(https://img-blog.csdnimg.cn/20190522000008399.jpg?x-oss-process=image/watermark,...

    shenhualong 評論0 收藏0
  • Javascript 深入淺出This

    摘要:中函數(shù)的調(diào)用有以下幾種方式作為對象方法調(diào)用,作為函數(shù)調(diào)用,作為構(gòu)造函數(shù)調(diào)用,和使用或調(diào)用。作為構(gòu)造函數(shù)調(diào)用中的構(gòu)造函數(shù)也很特殊,構(gòu)造函數(shù),其實就是通過這個函數(shù)生成一個新對象,這時候的就會指向這個新對象如果不使用調(diào)用,則和普通函數(shù)一樣。 this 是 JavaScript 比較特殊的關(guān)鍵字,本文將深入淺出的分析其在不同情況下的含義,可以這樣說,正確掌握了 JavaScript 中的 th...

    Y3G 評論0 收藏0
  • 學(xué)習(xí)React之前你需要知道的的JavaScript基礎(chǔ)知識

    摘要:和類在開始時遇到類組件,只是需要有關(guān)類的基礎(chǔ)。畢竟,中的條件呈現(xiàn)僅再次顯示大多數(shù)是而不是特定的任何內(nèi)容。 在我的研討會期間,更多的材料是關(guān)于JavaScript而不是React。其中大部分歸結(jié)為JavaScript ES6以及功能和語法,但也包括三元運算符,語言中的簡寫版本,此對象,JavaScript內(nèi)置函數(shù)(map,reduce,filter)或更常識性的概念,如:可組合性,可重用...

    bitkylin 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<