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

資訊專欄INFORMATION COLUMN

深入理解JavaScript中的this指向

不知名網(wǎng)友 / 910人閱讀

摘要:和作用域判別失敗相關(guān),而代表作用域判別成功,但是對結(jié)果的操作是非法的不合理的。在中,構(gòu)造函數(shù)只是使用操作符時被調(diào)用的函數(shù),它們并不屬于一個類,也不會實例化一個類。也就是說,中,不存在所謂的構(gòu)造函數(shù),只有對函數(shù)的構(gòu)造調(diào)用。

與其他語言相比,js中的this有所不同,也是比較頭疼的問題。在參考了一些資料后,今天,就來深入解析一下this指向問題,有不對的地方望大家指出。

為什么要用this

對于前端開發(fā)者來說,this是比較復(fù)雜的機制,那么為什么要花大量時間來學(xué)習(xí)呢,先來看一段代碼。
如果不使用this,要給identify( )和speak( )顯式傳入一個對象:

function identify(context) {
    return context.name.toUpperCase();
}
function speak(context) {
    var greeting = "Hello, I"m" + identify(context);
    console.log(greeting);
}
identify(you);
speak(me);

可以看到,speak( )里面直接寫了identify( )的函數(shù)名,然而,隨著使用模式越來越復(fù)雜,顯式傳遞的上下文會讓代碼變得混亂,尤其體現(xiàn)在面向?qū)ο笾小?br>顯然,this提供了一種方式來隱式“傳遞”一個對象的引用,更加簡潔,易于復(fù)用。

this的誤解 1. this指向函數(shù)本身

記錄函數(shù)foo被調(diào)用的次數(shù):

function foo(num) {
    console.log("foo:" + num);
    
    // 記錄次數(shù)
    this.count++;
}

foo.count = 0;

var i;

for (i = 0; i < 10; i++) {
    if (i > 5) {
        foo(i);
    }
}

// foo: 6
// foo: 7
// foo: 8
// foo: 9

//foo被調(diào)用了多少次?
console.log(foo.count); // 0

從前兩次的console.log( )可以看出,foo確實被調(diào)用了4次,但是foo.count仍然為0,顯然this指向函數(shù)本身的理解是錯誤的。

2. this指向函數(shù)作用域

要明確的是,this在任何情況下都不指向函數(shù)的詞法作用域。因為,作用域“對象”無法通過JavaScript代碼訪問,它存在于JavaScript引擎內(nèi)部。
下面的代碼試圖使用this來隱式引用函數(shù)的詞法作用域,沒有成功:

function foo() {
    var a = 2;
    this.bar();
}
function bar() {
    console.log(this.a);
}
foo(); // ReferenceError: a is not defined

直接報出了訪問不到foo( )中的a。ReferenceError和作用域判別失敗相關(guān),而TypeError代表作用域判別成功,但是對結(jié)果的操作是非法的、不合理的。

this是什么

排除了以上兩個誤解之后,來看一下this到底是什么。
this是運行時綁定的,它和函數(shù)聲明的位置沒有任何關(guān)系,只取決于函數(shù)的調(diào)用方式。當(dāng)一個函數(shù)被調(diào)用時,會創(chuàng)建一個活動記錄(執(zhí)行上下文),這個記錄包含函數(shù)在哪里被調(diào)用,函數(shù)的調(diào)用方式、傳入的參數(shù)等,this就是這個記錄的一個屬性,在函數(shù)執(zhí)行的過程中用到。即,this總是指向調(diào)用它所在方法的對象

1. 在瀏覽器中,調(diào)用方法沒有明確對象時,this指向window
function foo() {
    console.log(this.a);
}

var a = 2;

foo(); // 2

在全局中聲明變量a = 2,然后在全局中直接調(diào)用foo( ),this指向了全局對象,得到a的值。
要注意的是,在嚴(yán)格模式(strict mood)下,如果this沒有被執(zhí)行環(huán)境定義,那它將綁定為undefined。

function foo() {
    "use strict";
    
    console.log(this.a);
}

var a = 2;

foo(); // TypeError: this is undefined

在嚴(yán)格模式下,調(diào)用foo( )不影響this綁定。

function foo() {
    console.log(this.a);
}

var a = 2;

(function() {
    "use strict";
    
    foo(); // 2
})();
2. 在瀏覽器中,setTimeout、setInterval和匿名函數(shù)執(zhí)行時的當(dāng)前對象是全局對象window
function foo() {
    console.log(this.a);
}

var obj = {
    a: 2,
    foo: foo
};

var a = "global";

setTimeout(obj.foo, 100); // "global"

JavaScript中的setTimeout( )的實現(xiàn)和下面?zhèn)未a相似:

function setTimeout(fn, delay) {
    // 等待delay毫秒
    fn(); // 調(diào)用函數(shù)
}
3. apply / call / bind可以強制改變this指向
function foo() {
    console.log(this.a);
}

var obj = {
    a: 2
};

foo.call(obj); // 2
foo.apply(obj); // 2
foo.bind(obj); // 2

call和apply的區(qū)別在于第二個參數(shù),call是把args全部列出來,用“,”分隔,而apply是一個類數(shù)組。call、apply是硬綁定,通過硬綁定的函數(shù)不能再修改它的this。

function foo() {
    console.log(this.a);
}

var obj = {
    a: 2
};

var bar = function() {
    foo.call(obj);
}

bar(); // 2
setTimeout(bar, 100); // 2

bar.call(window); // 2

函數(shù)foo( )內(nèi)部手動調(diào)用了foo.call(obj),把foo的this強制綁定到了obj,所以后面即使又把bar( )綁定到了window,還是無法改變this指向。

4. new操作符改變this指向

在傳統(tǒng)的面向?qū)ο笳Z言中,會使用new初始化類,然而在JavaScript中new的機制和面向?qū)ο笳Z言完全不同。在js中,構(gòu)造函數(shù)只是使用new操作符時被調(diào)用的函數(shù),它們并不屬于一個類,也不會實例化一個類。也就是說,js中,不存在所謂的“構(gòu)造函數(shù)”,只有對函數(shù)的“構(gòu)造調(diào)用”。

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

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

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

優(yōu)先級

既然有那么多可以改變this的指向,那么它們的優(yōu)先級是怎么樣的呢,記住這句話:范圍越小,優(yōu)先級越高??梢园凑障旅娴捻樞騺砼袛啵?/p>

判斷函數(shù)是否在new中調(diào)用過:

var bar = new foo();

判斷函數(shù)是否通過call、apply、bind綁定過:

var bar = foo.call(obj);

判斷函數(shù)是否在某個上下文對象中調(diào)用過:

var bar = obj.foo();

如果以上情況均不存在,那么在嚴(yán)格模式下,綁定到undefined,否則綁定到全局對象:

var bar = foo();

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

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

相關(guān)文章

  • 我對JavaScriptthis的一些理解

    摘要:匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此它的對象通常指向。如果對此有疑惑,可以看知乎上的答案知乎匿名函數(shù)的指向為什么是作為對象方法的調(diào)用,指向該對象當(dāng)函數(shù)作為某個對象的方法調(diào)用時,就指這個函數(shù)所在的對象。 因為日常工作中經(jīng)常使用到this,而且在JavaScript中this的指向問題也很容易讓人混淆一部分知識。 這段時間翻閱了一些書籍也查閱了網(wǎng)上一些資料然后結(jié)合自己的經(jīng)驗,為了能讓自...

    focusj 評論0 收藏0
  • Javascript深入理解this作用域問題以及new/let/var/const對this

    摘要:理解作用域高級程序設(shè)計中有說到對象是在運行時基于函數(shù)的執(zhí)行環(huán)境綁定的在全局函數(shù)中,等于,而當(dāng)函數(shù)被作為某個對象調(diào)用時,等于那個對象。指向與匿名函數(shù)沒有關(guān)系如果函數(shù)獨立調(diào)用,那么該函數(shù)內(nèi)部的,則指向。 理解this作用域 《javascript高級程序設(shè)計》中有說到: this對象是在運行時基于函數(shù)的執(zhí)行環(huán)境綁定的:在全局函數(shù)中,this等于window,而當(dāng)函數(shù)被作為某個對象調(diào)用時,t...

    snowLu 評論0 收藏0
  • JavaScriptthis指向深入解析

    普通函數(shù)的this指向 簡單說說 首先,按照慣例,我們先舉個栗子: var bar = 2; function foo() { this.bar = 1; this.getBar = function() { console.log(this.bar); } } var test = new foo(); var getBar = test.getBar; test.getB...

    AlphaGooo 評論0 收藏0
  • 深入理解 Javascriptthis

    摘要:深入淺出的理解問題的由來寫法一寫法二雖然和指向同一個函數(shù),但是執(zhí)行結(jié)果可能不一樣。該變量由運行環(huán)境提供。所以,就出現(xiàn)了,它的設(shè)計目的就是在函數(shù)體內(nèi)部,指代函數(shù)當(dāng)前的運行環(huán)境。 深入淺出this的理解 問題的由來 var obj = { foo: function(){} } var foo = obj.foo; // 寫法一 obj.foo(); // 寫法二 foo...

    OnlyMyRailgun 評論0 收藏0
  • 深入理解JavaScript(三):獲取數(shù)組中的最大值方法(this,apply)

    摘要:三個方法的作用,都是改變的指向,只是用法稍微有些區(qū)別什么是既不指向函數(shù)自身,也不指函數(shù)的詞法作用域。它在函數(shù)定義的時候是確定不了的在函數(shù)被調(diào)用時才發(fā)生的綁定,也就是說具體指向什么,取決于你是怎么調(diào)用的函數(shù)。 1.排序法 思路:給數(shù)組先排序(由大到小排序),第一項就是最大值 let arr = [1,5,6,7,9,20,40,2,3]; let max1 = arr.sort(func...

    canopus4u 評論0 收藏0

發(fā)表評論

0條評論

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