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

資訊專欄INFORMATION COLUMN

js 中 this 的詳細解釋

xiangzhihong / 2139人閱讀

摘要:是中很重要的一個指針。一起學習以下你不知道的中關(guān)于的介紹調(diào)用棧和調(diào)用位置每個函數(shù)的是在調(diào)用時被綁定的,完全取決于函數(shù)的調(diào)用位置也就是函數(shù)的調(diào)用方法。調(diào)用棧就是為了到達當前執(zhí)行位置所調(diào)用的所有函數(shù)。

this 是js 中很重要的一個指針。但是往往也是最容易產(chǎn)生bug 的地方。一起學習以下《你不知道的JavaScript》中關(guān)于this的介紹;

調(diào)用棧 和 調(diào)用位置
每個函數(shù)的this是在調(diào)用時被綁定的,完全取決于函數(shù)的調(diào)用位置(也就是函數(shù)的調(diào)用方法)。

在理解this的綁定過程之前,首先要理解調(diào)用位置和調(diào)用棧;因為 調(diào)用位置 就在 當前正在執(zhí)行的函數(shù)前一個調(diào)用 中。

什么是調(diào)用棧和調(diào)用位置
調(diào)用位置:調(diào)用位置就是函數(shù)在代碼中被調(diào)用的位置(而不是聲明的位置)。
調(diào)用棧:就是為了到達當前執(zhí)行位置所調(diào)用的所有函數(shù)。

function baz() {
    // 當前調(diào)用棧是:baz
    // 因此, 當前調(diào)用位置是全局作用域
    console.log( "baz" );
    bar(); // <-- bar的調(diào)用位置
} 
function bar() {
    // 當前調(diào)用棧是baz -> bar
    // 因此, 當前調(diào)用位置在baz中
    console.log( "bar" );
    foo(); // <-- foo的調(diào)用位置
} 
function foo() {
    // 當前調(diào)用棧是baz -> bar -> foo
    // 因此, 當前調(diào)用位置在bar中
    console.log( "foo" );
} 
baz(); // <-- baz的調(diào)用位置
this綁定規(guī)則1:默認模式

分析代碼:

function foo() {
    console.log( this.a );
    //this通過默認綁定指向全局對象
} 
var a = 2;
foo(); // 2

function foo() {
    "use strict";
    console.log( this.a ); 
    //嚴格模式(strict mode)全局對象將無法使用默認綁定
} 
var a = 2;
foo(); // TypeError: this is undefined

解釋:

可以把這條規(guī)則看作是無法應(yīng)用其他規(guī)則時的默認規(guī)則。

當調(diào)用foo()時,this.a被解析成了全局變量a。為什么?因為在本例中,函數(shù)調(diào)用時應(yīng)用了this的默認綁定,因此this指向全局對象。

foo()是直接使用不帶任何修飾的函數(shù)引用進行調(diào)用的,因此只能使用默認綁定,無法應(yīng)用其他規(guī)則。

如果使用嚴格模式(strict mode),那么全局對象將無法使用默認綁定,因此this會綁定到undefined

this綁定規(guī)則2:隱式綁定

分析代碼:

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

解析:

無論是直接在obj中定義還是先定義再添加為引用屬性,foo嚴格來說都不屬于obj對象。

調(diào)用位置會使用obj上下文來引用函數(shù),因此你可以說函數(shù)被調(diào)用時obj對象“擁有”或者“包含”它。

當函數(shù)引用有上下文對象時,隱式綁定規(guī)則會把函數(shù)調(diào)用中的this綁定到這個上下文對象。

對象屬性引用鏈中只有最接近(包含層)會影響調(diào)用位置。

隱式丟失

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

if(bar === obj.foo){
    console.log("true"); //true
    console.log(typeof bar) //function
    console.log(typeof obj.foo)  //function
}else {
    console.log("false")
} 

bar(); // "oops, global"
obj.foo();// 2

//等價的兩個函數(shù),輸出不一樣的結(jié)果。為什么?
//其實var bar === window.bar; 它隱式綁定了window 對象,所以它訪問到的自然是 window.a

解析:雖然bar是obj.foo的一個引用,但是實際上,它引用的是foo函數(shù)本身,因此此時的bar()其實是一
個不帶任何修飾的函數(shù)調(diào)用,因此應(yīng)用了默認綁定。這種情況是不可以預料的。

還有一種 this 丟失=》 回調(diào)函數(shù)

回調(diào)函數(shù)丟失this綁定是非常常見的

function foo() {
console.log( this.a );
}
function doFoo(fn) {
    // fn其實引用的是foo
    fn(); // <-- 調(diào)用位置!
} 
var obj = {
    a: 2,
    foo: foo
};
var a = "oops, global"; // a是全局對象的屬性
doFoo( obj.foo ); // "oops, global"
this綁定規(guī)則3:顯式綁定

分析代碼:

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

通過foo.call(..),我們可以在調(diào)用foo時強制把它的this綁定到obj上

硬綁定

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

bind(..)會返回一個硬編碼的新函數(shù),它會把參數(shù)設(shè)置為this的上下文并調(diào)用原始函數(shù)。

this綁定規(guī)則4:new綁定

JavaScript,構(gòu)造函數(shù)只是一些使用new操作符時被調(diào)用的函數(shù)。它們并不會屬于某個類,也不會實例化一個類。實際上,它們甚至都不能說是一種特殊的函數(shù)類型,它們只是被new操作符調(diào)用的普通函數(shù)而已。

使用new來調(diào)用函數(shù)時的行為

創(chuàng)建(或者說構(gòu)造)一個全新的對象

新對象會被執(zhí)行[[原型]]連接。

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

如果函數(shù)沒有返回其他對象,那么new表達式中的函數(shù)調(diào)用會自動返回這個新對象。

function foo(a) {
    this.a = a;
} 
//new對普通函數(shù)的構(gòu)造調(diào)用,默認行為:創(chuàng)建一個新對象,獲得對this的所有引用,返回新對象。
var bar = new foo(2);
console.log( bar.a ); // 2

//以上函數(shù) 相當于下面的函數(shù)

function foo(a){
    var obj = {};
    obj.a = a;
    reture obj
}
var bar = foo(2);
console.log( bar.a ); // 2

解析:使用new來調(diào)用foo(..)時,我們會構(gòu)造一個新對象并把它綁定到foo(..)調(diào)用中的this上。

綁定優(yōu)先級

顯式綁定 > 隱式綁定
bind硬綁定 > new綁定 > 隱式綁定

判斷步驟

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

var bar = new foo()

函數(shù)是否通過call、apply(顯式綁定)或者硬綁定調(diào)用?如果是的話,this綁定的是指定的對象。

function foo(a) {
    this.a = a;
}
var obj = {
    a:2
}
foo.call(obj,3); 
//因為強制改變了foo 的上下文,this 顯示綁定 為 obj;所以改變的是obj.a 的值 
console.log(obj.a); //3 

函數(shù)是否在某個上下文對象中調(diào)用(隱式綁定)?如果是的話,this綁定的是那個上下文對象。

var bar = obj1.foo()

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

var bar = foo()

在默認綁定中容易被混淆的是 IIFE 自執(zhí)行函數(shù)的使用

var a = 3;
var obj = {
    a:3,
    b:(function(){
        console.log(this.a)
    })(),
    c:function(){
        (function(){
            console.log(this.a)
        })()
    }
}
obj.c();

  //3
  //3

  this 都指向了window 

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

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

相關(guān)文章

  • 前端技能拾遺

    摘要:本文主要是對自己前端知識遺漏點的總結(jié)和歸納,希望對大家有用,會持續(xù)更新的解釋語言和編譯型語言解釋型語言與編譯型語言的區(qū)別翻譯時間的不同。命令會有變量聲明提前的效果。硬綁定參考不同是返回對應(yīng)函數(shù),便于稍后調(diào)用則是立即調(diào)用。 本文主要是對自己前端知識遺漏點的總結(jié)和歸納,希望對大家有用,會持續(xù)更新的~ 解釋語言和編譯型語言 解釋型語言與編譯型語言的區(qū)別翻譯時間的不同。編譯型語言在程序執(zhí)行之前...

    lyning 評論0 收藏0
  • 前端技能拾遺

    摘要:本文主要是對自己前端知識遺漏點的總結(jié)和歸納,希望對大家有用,會持續(xù)更新的解釋語言和編譯型語言解釋型語言與編譯型語言的區(qū)別翻譯時間的不同。命令會有變量聲明提前的效果。硬綁定參考不同是返回對應(yīng)函數(shù),便于稍后調(diào)用則是立即調(diào)用。 本文主要是對自己前端知識遺漏點的總結(jié)和歸納,希望對大家有用,會持續(xù)更新的~ 解釋語言和編譯型語言 解釋型語言與編譯型語言的區(qū)別翻譯時間的不同。編譯型語言在程序執(zhí)行之前...

    Vultr 評論0 收藏0
  • 前端技能拾遺

    摘要:本文主要是對自己前端知識遺漏點的總結(jié)和歸納,希望對大家有用,會持續(xù)更新的解釋語言和編譯型語言解釋型語言與編譯型語言的區(qū)別翻譯時間的不同。命令會有變量聲明提前的效果。硬綁定參考不同是返回對應(yīng)函數(shù),便于稍后調(diào)用則是立即調(diào)用。 本文主要是對自己前端知識遺漏點的總結(jié)和歸納,希望對大家有用,會持續(xù)更新的~ 解釋語言和編譯型語言 解釋型語言與編譯型語言的區(qū)別翻譯時間的不同。編譯型語言在程序執(zhí)行之前...

    kevin 評論0 收藏0
  • JavaScript錯誤正確處理方式,你用對了嗎?

    摘要:單元測試會體現(xiàn)出以上錯誤處理程序的作用如果出現(xiàn)問題,錯誤處理程序就會返回。同時錯誤會展開堆棧,這對調(diào)試非常有幫助。展開堆棧處理異常的一種方式是在調(diào)用堆棧的頂部加入。確保你的錯誤處理處在相同域中,這樣會保留原始消息,堆棧和自定義錯誤對象。 JavaScript的事件驅(qū)動范式增添了豐富的語言,也是讓使用JavaScript編程變得更加多樣化。如果將瀏覽器設(shè)想為JavaScript的事件驅(qū)動...

    chaos_G 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<