欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
JavaScript 中的 this 并不難

js中的this,如果沒(méi)有深入的學(xué)習了解,那么this將會(huì )是讓開(kāi)發(fā)人員很頭疼的問(wèn)題。下面,我就針對this,來(lái)做一個(gè)學(xué)習筆記。

1.調用位置

在理解this的綁定過(guò)程之前,首先要理解調用位置:調用位置就是函數在代碼中被調用的位置(而不是聲明的位置)。只有分析好調用位置,才能明白這個(gè)this到底引用的是什么?
尋找調用位置,最重要的是分析調用棧(就是為了到達當前執行位置所調用的所有函數)。調用位置就在當前正在執行的前一個(gè)調用中。
下面舉例說(shuō)明:

function baz (){    // 當前調用棧是:baz    //因此,當前調用位置是全局作用域    console.log("baz");    bar();// <-- bar的調用位置}function bar(){    // 當前調用棧是 baz -> bar    // 因此,當前調用位置在 baz 中    console.log('bar');    foo();// <-- foo 的調用位置}function foo(){    // 當前調用棧是baz -> bar -> foo    // 因此,當前調用位置在bar中    console.log("foo");}baz(); // <-- baz的調用位置

2.綁定規則

2.1 默認綁定

首先看一下最常用的函數調用類(lèi)型:獨立函數調用??梢园堰@條規則看作是無(wú)法應用其他規則時(shí)的默認規則。
如下例:

function foo() {    console.log(this.a);}var a = 2;foo(); // 2// 在本代碼中,foo() 是直接使用不帶任何修飾的函數引用進(jìn)行調用的,因此只能使用默認綁定,無(wú)法應用其他規則。// 如果使用嚴格模式,那么全局對象無(wú)法使用默認綁定,因此this會(huì )綁定到undefined。

2.2 隱式綁定

另一條需要考慮的規則是調用位置是否有上下文對象,或者說(shuō)是否被某個(gè)對象擁有或者包含。舉例來(lái)說(shuō):

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

首先要注意的是foo()的聲明方式,以及之后是如何被當做引用屬性添加到obj的。但是無(wú)論是直接在obj中定義還是先定義再添加為引用屬性,這個(gè)函數嚴格來(lái)說(shuō)都不屬于obj 對象。

然而,調用位置會(huì )使用obj的上下文來(lái)引用函數,因此,可以說(shuō)函數被調用時(shí)obj對象“擁有”或者“包含”它。

無(wú)論如何稱(chēng)呼這個(gè)模式,當foo()被調用時(shí),落腳點(diǎn)確實(shí)指向obj對象。當函數引用有上下文對象時(shí),隱式綁定規則會(huì )把函數調用中的this綁定到這個(gè)上下文對象。所以this.a和obj.a是一樣的。

對象屬性引用鏈中只有最后一層會(huì )影響調用位置。上代碼:

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

2.2.1 隱式丟失

一個(gè)最常見(jiàn)額this綁定問(wèn)題就是被隱式綁定的函數會(huì )丟失綁定對象,會(huì )應用默認綁定,從而把this綁定到全局對象或者undefined上,取決于是否是嚴格模式??聪旅娴拇a:

function foo() {    console.log(this.a);}var obj = {    a:2,    foo};var bar = obj.foo; // 函數別名!var a = "What?"; // a 是全局對象的屬性bar();//"What?"

雖然bar是obj.foo 的一個(gè)引用,但是實(shí)際上,它引用的是foo函數本身,因此此時(shí)的bar()其實(shí)是一個(gè)不帶任何修飾符的函數調用,因此應用了默認綁定。
下面舉一個(gè)回調函數中隱式丟失的例子:

function foo() {    console.log(this.a);}function doFoo(fn){    // fn 其實(shí)引用的是foo    fn(); // <- 調用位置}var obj = {    a:2,    foo};var a = "What?"; // a 是全局對象的屬性doFoo(obj.foo);//"What?"

參數傳遞其實(shí)就是一種隱式賦值,傳入函數時(shí)也會(huì )被隱式賦值,所以結果和上一個(gè)例子一樣。

2.3 顯示綁定

在上面隱式綁定的時(shí)候,必須在一個(gè)對象內部包含一個(gè)指向函數的屬性,并通過(guò)這個(gè)屬性間接引用函數,從而把this間接(隱式)的綁定到這個(gè)對象上。

如果我們不想在對象內部包含函數引用,而想在某個(gè)對象上強制調用函數,該如何處理?

基本上大部分函數會(huì )包含call(..)和apply(..)方法。但是有的時(shí)候JavaScript的宿主環(huán)境有時(shí)候會(huì )提供一些非常特殊的函數,可能沒(méi)有這兩個(gè)方法,但是極為罕見(jiàn)。

這兩個(gè)函數的第一個(gè)參數是一個(gè)對象,會(huì )把這個(gè)對象綁定到this,接著(zhù)在調用函數時(shí)指定這個(gè)this。因為這種方式可以直接指定this的綁定對象,因此我們稱(chēng)之為顯示綁定。

上代碼:

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

通過(guò)foo.call(...),我們可以在調用foo的時(shí)候強制將this綁定在obj上。

如果從傳入了一個(gè)原始值(字符串類(lèi)型、布爾類(lèi)型或者數字類(lèi)型)來(lái)當做this的綁定對象,這個(gè)原始值會(huì )被轉換成它的對象形式(也就是new String(...)、new Boolean(...)或者new Number(...)),這通常稱(chēng)為“裝箱”。

從this的綁定的角度來(lái)說(shuō),call(...)和apply(...)是一樣的,他們的區別體現在其他的參數上。

不過(guò)上述的代碼不能很好地解決我們提出的丟失綁定的問(wèn)題。

2.3.1 硬綁定

不過(guò)顯示綁定的一個(gè)變種可以解決這個(gè)問(wèn)題。
上代碼:

function foo() {    console.log(this.a);}var obj = {    a:2};var bar = function(){    foo.call(obj);}var a = '123';bar(); // 2 setTimeout(bar,10); // 2bar.call(window); // 2 此時(shí)硬綁定的bar不能修改foo的this。foo總會(huì )在obj上調用。

由于硬綁定是一種非常常用的模式,所以在ES5中提供了內置方法 bind ,它的用法如下:

function foo(str) {    console.log(this.a, str)    return this.a + str;}var obj = {    a: 2};var bar = foo.bind(obj);var b = bar(3);// 2 3console.log(b);// 5

2.3.2 API調用的“上下文”

第三方庫的許多函數,以及javaScript語(yǔ)言和宿主環(huán)境中的許多新的內置函數,都提供了一個(gè)可選的參數,通常被稱(chēng)為上下文,其作用和bind一樣,確?;卣{函數使用指定的this。上代碼:

function foo (item){    console.log(item,this.id);}var obj = {    id:"cool"};// 調用foo()時(shí)把this綁定到obj[1,2,3].forEach(foo,obj);// 1 cool 2 cool 3 cool

2.4 new綁定

js中使用new可以構造一個(gè)新的對象,使用new來(lái)調用函數,或者說(shuō)發(fā)生構造函數調用時(shí),會(huì )自動(dòng)執行下面的操作。

  1. 創(chuàng )建(或者說(shuō)構造)一個(gè)全新的對象;

  2. 創(chuàng )建這個(gè)新對象會(huì )被執行[[原型]]連接;

  3. 這個(gè)新對象會(huì )綁定到函數調用的this;

  4. 如果函數沒(méi)有返回其他對象,那么new表達式中的函數調用會(huì )自動(dòng)返回這個(gè)新對象。

上代碼:

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

使用new來(lái)調用foo()時(shí),會(huì )構造一個(gè)新對象并綁定到foo()調用中的this上。

3.優(yōu)先級。

  • 毫無(wú)疑問(wèn),默認綁定的優(yōu)先級是最低的。

那么隱式綁定和顯示綁定誰(shuí)更高?上代碼:

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

可以看到,顯式綁定優(yōu)先級更高,也就是說(shuō)在判斷時(shí)應當先考慮是否可以應用顯式綁定。

  • new 綁定 VS 隱式綁定:

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

可以看到 new 綁定比隱式綁定優(yōu)先級高。

  • new 綁定 VS 顯示綁定:

new 和 call/apply 無(wú)法一起使用,因此無(wú)法通過(guò) new foo.call(obj1) 來(lái)直接
進(jìn)行測試。但是我們可以使用硬綁定來(lái)測試它倆的優(yōu)先級。

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

可以看到,new 修改了硬綁定(到 obj1 的)調用 bar(..) 中的 this。因為使用了new 綁定,我們得到了一個(gè)名字為 baz 的新對象,并且 baz.a 的值是 3。

總結

現在我們可以根據優(yōu)先級來(lái)判斷函數在某個(gè)調用位置應用的是哪條規則??梢园凑障旅娴?br>順序來(lái)進(jìn)行判斷:
1.函數是否在 new 中調用(new 綁定)?如果是的話(huà) this 綁定的是新創(chuàng )建的對象。

var bar = new foo()

2.函數是否通過(guò) call、apply(顯式綁定)或者硬綁定調用?如果是的話(huà),this 綁定的是指定的對象

var bar = foo.call(obj2)

3.函數是否在某個(gè)上下文對象中調用(隱式綁定)?如果是的話(huà),this 綁定的是那個(gè)上下文對象。

var bar = obj1.foo()

4.如果都不是的話(huà),使用默認綁定。如果在嚴格模式下,就綁定到 undefined,否則綁定到全局對象。

var bar = foo()

4.箭頭函數

之前介紹的四條規則已經(jīng)可以包含所有正常的函數。但是 ES6 中介紹了一種無(wú)法使用這些規則的特殊函數類(lèi)型:箭頭函數。
箭頭函數并不是使用 function 關(guān)鍵字定義的,而是使用被稱(chēng)為“胖箭頭”的操作符 => 定義的。箭頭函數不使用 this 的四種標準規則,而是根據外層(函數或者全局)作用域來(lái)決定 this。

function foo() {     // 返回一個(gè)箭頭函數     return (a) => {     //this 繼承自 foo()     console.log( this.a );  };}var obj1 = {      a:2};var obj2 = {      a:3 };var bar = foo.call( obj1 );bar.call( obj2 ); // 2, 不是 3 !

foo() 內部創(chuàng )建的箭頭函數會(huì )捕獲調用時(shí) foo() 的 this。由于 foo() 的 this 綁定到 obj1,
bar(引用箭頭函數)的 this 也會(huì )綁定到 obj1,箭頭函數的綁定無(wú)法被修改。(new 也不
行?。?/p>

箭頭函數最常用于回調函數中,例如事件處理器或者定時(shí)器:

function foo() {      setTimeout(() => {     // 這里的 this 在此法上繼承自 foo()     console.log( this.a );  },100);}var obj = {      a:2};foo.call( obj ); // 2

箭頭函數可以像 bind(..) 一樣確保函數的 this 被綁定到指定對象,此外,其重要性還體
現在它用更常見(jiàn)的詞法作用域取代了傳統的 this 機制。實(shí)際上,在 ES6 之前我們就已經(jīng)
在使用一種幾乎和箭頭函數完全一樣的模式。

function foo() {     var self = this; // lexical capture of this      setTimeout( function(){     console.log( self.a );     }, 100 );} var obj = {     a: 2};foo.call( obj ); // 2

雖然 self = this 和箭頭函數看起來(lái)都可以取代 bind(..),但是從本質(zhì)上來(lái)說(shuō),它們想替
代的是 this 機制。

參考資料

  • 《你不知道的javaScript》---上卷

你好!我是 JHCan333,公眾號:愛(ài)生活的前端狗的作者。公眾號專(zhuān)注前端工程師方向,包括但不限于技術(shù)提高、職業(yè)規劃、生活品質(zhì)、個(gè)人理財等方面,會(huì )持續發(fā)布優(yōu)質(zhì)文章,從各個(gè)方面提升前端開(kāi)發(fā)的幸福感。關(guān)注公眾號,我們一起向前走!

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
談"this"
JavaScript 中的 this 全面解析
徹底弄懂js中this指向(包含js綁定、優(yōu)先級、面試題詳解)
this綁定方式和優(yōu)先級比較
JS的綁定對象this
This 帶來(lái)的困惑
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久