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

資訊專欄INFORMATION COLUMN

輕松搞定javascript中this的指向

shinezejian / 2386人閱讀

摘要:調(diào)用在中,通過(guò)的形式調(diào)用一個(gè)構(gòu)造函數(shù),會(huì)創(chuàng)建這個(gè)構(gòu)造函數(shù)實(shí)例,而這個(gè)實(shí)例的指向創(chuàng)建的這個(gè)實(shí)例。如下例所示,在構(gòu)造函數(shù)內(nèi)部使用并沒(méi)有改變?nèi)肿兞康闹怠o@然,箭頭函數(shù)是不能用來(lái)做構(gòu)造函數(shù)。

  關(guān)于javascript中this指向的問(wèn)題,現(xiàn)總結(jié)如下,如有不正確,歡迎指正。

  javascript中,this的指向并不是在函數(shù)定義的時(shí)候確定的,而是在其被調(diào)用的時(shí)候確定的。也就是說(shuō),函數(shù)的調(diào)用方式?jīng)Q定了this指向。記?。?b>this 就是一個(gè)指針,指向我們調(diào)用函數(shù)的對(duì)象。

  在此將javascript中this的調(diào)用方式分為以下幾種:

1、直接調(diào)用:

  直接調(diào)用是指通過(guò) funName(..) 這種方式調(diào)用。此時(shí),函數(shù)內(nèi)部的this指向全局變量。

function foo() {
    console.log(this === global);
}
foo(); //true

  注意:直接調(diào)用并不是僅僅指在全局作用域下進(jìn)行調(diào)用,而是說(shuō)在任何作用域下通過(guò)funName(..) 這種方式調(diào)用。如下兩個(gè)例子亦是屬于直接調(diào)用方式:

  a、使用bind函數(shù)改變外層函數(shù)的作用域,然后在內(nèi)層直接調(diào)用,其this指向依然是全局變量:

function foo() {
    console.log(this === global);
}

function foo1() {
    foo();
};
var foo2 = foo1.bind({}); //改變foo1函數(shù)的作用域
foo2(); //true 依然指向全局變量

  b、函數(shù)表達(dá)式,將一個(gè)函數(shù)賦值給一個(gè)變量,然后通過(guò)直接調(diào)用的調(diào)用方式調(diào)用此函數(shù),其this指向依然是全局變量:

var obj = {
    foo: function(){
        console.log(this === obj);   //false
        console.log(this === global);//true
    }
}
var f = obj.foo;
f();
2、方法調(diào)用:

  方法調(diào)用是指通過(guò)對(duì)象來(lái)調(diào)用其方法函數(shù),類似于obj.foo(..)的調(diào)用方式。此時(shí),this指向調(diào)用該方法的對(duì)象,注意,是最終調(diào)用該方法的對(duì)象。

var obj = {
    foo1: function(){
        console.log(this === obj);
    }
}
obj.foo2 = function() {
    console.log(this === obj);
}
function foo3() {
    console.log(this === obj);
}
obj.foo3 = foo3;
obj.foo1(); // true
obj.foo2(); // true
obj.foo3(); // true
3、new 調(diào)用:

  在es5中,通過(guò) new Constructor() 的形式調(diào)用一個(gè)構(gòu)造函數(shù),會(huì)創(chuàng)建這個(gè)構(gòu)造函數(shù)實(shí)例,而這個(gè)實(shí)例的this指向創(chuàng)建的這個(gè)實(shí)例。如下例所示,在構(gòu)造函數(shù)內(nèi)部使用this.name并沒(méi)有改變?nèi)肿兞縩ame的值。

var name = "全局";
function Person(name){
    this.name = name;
}
var p = new Person("局部");
console.log(p.name);
console.log(name);

上述三種情況是常見(jiàn)的調(diào)用方式,以下還有一些特殊的調(diào)用方式:如bind、call、apply以及es6中箭頭函數(shù)。

4、bind函數(shù)對(duì)this的影響

  bind函數(shù)用于綁定this的指向,并且返回一個(gè)綁定函數(shù),此函數(shù)綁定了this指向,注意:綁定函數(shù)的this指向?qū)⒉豢稍俅胃摹?/p>

var obj = {};
function foo1() {
    console.log(this === obj);
}
foo1(); //false  此時(shí)屬于上述直接調(diào)用的方式,因此其this指向global
var foo2 = foo1.bind(obj);
foo2(); //true 綁定函數(shù)的this指向其綁定的對(duì)象
/**
 * 注意:綁定函數(shù)的this指向不可更改
 */
var foo3 = foo2.bind({"a": 1});
foo3(); //true 
foo2.apply({"a": 1}); //true 
foo2.call({"a": 1});  //true 
5、apply和call對(duì)this指向的影響

  apply和call亦可以用于改變this指向,并且返回執(zhí)行結(jié)果。關(guān)于bind、apply和call的區(qū)別以及實(shí)現(xiàn)可以參考我的博客:《bind、call、apply的區(qū)別與實(shí)現(xiàn)》,在此不做重復(fù)說(shuō)明。需要注意的一點(diǎn)是:apply和call不可以改變綁定函數(shù)(使用bind返回的函數(shù))的this指向。

var obj = {};
function foo1() {
    console.log(this === obj);
}
var foo2 = foo1.bind({"a": 1});
/**
 * 注意:此處并不是綁定函數(shù),因此其返回值依然是ture,即apply改變其this指向。
 */
foo1.apply(obj); //true
/**
 * 注意:此處是綁定函數(shù),因此不可再通過(guò)apply和call的形式改變其this指向。
 */
foo2.apply(obj); //false
6、es6箭頭函數(shù)中的this

  箭頭函數(shù)沒(méi)有自己的this綁定,其使用的this是其直接父級(jí)函數(shù)的this。也就是說(shuō),箭頭函數(shù)內(nèi)部的this是由其直接外層函數(shù)(方法)決定的,而外層函數(shù)中的this是由其調(diào)用方式?jīng)Q定的。

const obj = {
    foo: function() {
        const inner = () => {
            console.log(this === obj);
        };
        inner();
    },
    far: function() {
        return () => {
            console.log(this === obj);
        }
    }
}
/**
 * inner()內(nèi)的this是foo的this,其指向取決于foo的調(diào)用方式
 */
obj.foo(); //true
var foo1 = obj.foo;
foo1();    //false 此時(shí)應(yīng)該指向global

const far1 = obj.far();
far1();    //true
const far2 = obj.far;
far2()();  //false 此時(shí)應(yīng)該指向global
6.1 箭頭函數(shù)常見(jiàn)錯(cuò)誤及其解決方案:

在對(duì)象上定義函數(shù):

const test = {
    array: [1, 2, 3],
    sum: () => {
        console.log(this === window); // => true
        return this.array.reduce((result, item) => result + item);
    }
};
test.sum();
// TypeError: Cannot read property "reduce" of undefined

原因就是,箭頭函數(shù)沒(méi)有它自己的this值,箭頭函數(shù)內(nèi)的this值繼承自外圍作用域。

對(duì)象方法內(nèi)的this指向調(diào)用這個(gè)方法的對(duì)象,如果使用箭頭函數(shù),this和對(duì)象方法在調(diào)用的時(shí)候所處環(huán)境的this值一致。因?yàn)?test.sum()是在全局環(huán)境下進(jìn)行調(diào)用,此時(shí)this指向全局。

解決方法也很簡(jiǎn)單,使用函數(shù)表達(dá)式或者方法簡(jiǎn)寫(ES6 中已經(jīng)支持)來(lái)定義方法,這樣能確保 this 是在運(yùn)行時(shí)是由包含它的上下文決定的。

const test = {
    array: [1, 2, 3],
    sum() {
        console.log(this === test); // => true
        return this.array.reduce((result, item) => result + item);
    }
};
test.sum();
// 6

定義原型方法

在對(duì)象原型上定義函數(shù)也是遵循著一樣的規(guī)則

function Person(name) {
    this.name = name;
}

Person.prototype.sayName = () => {
    console.log(this === window); // => true
    return this.name;
};

const cat = new Person("Mew");
cat.sayName(); // => undefined

使用傳統(tǒng)的函數(shù)表達(dá)式就能解決問(wèn)題

function Person(name) {
    this.name = name;
}

Person.prototype.sayName = function() {
    console.log(this === Person); // => true
    return this.name;
};

const cat = new Person("Mew");
cat.sayName(); // => Mew

定義事件回調(diào)函數(shù)

thisJS中非常強(qiáng)大的特點(diǎn),他讓函數(shù)可以根據(jù)其調(diào)用方式動(dòng)態(tài)的改變上下文,然后箭頭函數(shù)直接在聲明時(shí)就綁定了this對(duì)象,所以不再是動(dòng)態(tài)的。

在客戶端,在DOM元素上綁定事件監(jiān)聽(tīng)函數(shù)是非常普遍的行為,在DOM事件被觸發(fā)時(shí),回調(diào)函數(shù)中的this指向該DOM,但是,箭頭函數(shù)在聲明的時(shí)候就綁定了執(zhí)行上下文,要?jiǎng)討B(tài)改變上下文是不可能的,在需要?jiǎng)討B(tài)上下文的時(shí)候它的弊端就凸顯出來(lái):

const button = document.getElementById("myButton");
button.addEventListener("click", () => {
    console.log(this === window); // => true
    this.innerHTML = "Clicked button";
});

因?yàn)檫@個(gè)回調(diào)的箭頭函數(shù)是在全局上下文中被定義的,所以他的thiswindow。換句話說(shuō)就是,箭頭函數(shù)預(yù)定義的上下文是不能被修改的,這樣 this.innerHTML 就等價(jià)于 window.innerHTML,而后者是沒(méi)有任何意義的。

使用函數(shù)表達(dá)式就可以在運(yùn)行時(shí)動(dòng)態(tài)的改變 this

const button = document.getElementById("myButton");
button.addEventListener("click", function() {
    console.log(this === button); // => true
    this.innerHTML = "Clicked button";
});

定義構(gòu)造函數(shù)

如果使用箭頭函數(shù)會(huì)報(bào)錯(cuò)。
顯然,箭頭函數(shù)是不能用來(lái)做構(gòu)造函數(shù)。

const Message = (text) => {
    this.text = text;
};
const helloMessage = new Message("Hello World!");
// Throws "TypeError: Message is not a constructor"

理論上來(lái)說(shuō)也是不能這么做的,因?yàn)榧^函數(shù)在創(chuàng)建時(shí)this對(duì)象就綁定了,更不會(huì)指向?qū)ο髮?shí)例。

箭頭函數(shù)帶來(lái)了很多便利。恰當(dāng)?shù)氖褂眉^函數(shù)可以讓我們避免使用早期的.bind()函數(shù)或者需要固定上下文的地方并且讓代碼更加簡(jiǎn)潔。

箭頭函數(shù)帶來(lái)了很多便利。恰當(dāng)?shù)氖褂眉^函數(shù)可以讓我們避免使用早期的.bind()函數(shù)或者需要固定上下文的地方并且讓代碼更加簡(jiǎn)潔。

  以上是個(gè)人對(duì)JavaScript中this的理解,歡迎您的留言。
歡迎訪問(wèn)我的個(gè)人博客了解更多信息。

參考文獻(xiàn):
1、《JavaScript 的 this 指向問(wèn)題深度解析》
2、《ES6使用箭頭函數(shù)注意點(diǎn)》

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

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

相關(guān)文章

  • 一次搞定this和閉包

    摘要:他的組成如下對(duì)的就是你關(guān)注的那個(gè)變量對(duì)象作用域鏈跟閉包相關(guān)由于是單線程的,一次只能發(fā)生一件事情,其他事情會(huì)放在指定上下文棧中排隊(duì)。 閉包和this,是兩個(gè)相當(dāng)高頻的考點(diǎn),然而你有沒(méi)有想過(guò),實(shí)際上他們兩個(gè)都跟同一個(gè)知識(shí)點(diǎn)相關(guān)? 有請(qǐng)我們的這篇文章的主角,執(zhí)行上下文 執(zhí)行上下文 執(zhí)行上下文是什么 可以簡(jiǎn)單理解執(zhí)行上下文是js代碼執(zhí)行的環(huán)境,當(dāng)js執(zhí)行一段可執(zhí)行代碼時(shí),會(huì)創(chuàng)建對(duì)應(yīng)的執(zhí)行上下文...

    Airy 評(píng)論0 收藏0
  • 前端基礎(chǔ)進(jìn)階(十一):詳細(xì)圖解jQuery對(duì)象,以及如何擴(kuò)展jQuery插件

    摘要:而在構(gòu)造函數(shù)中,返回了的實(shí)例對(duì)象。在中直接返回過(guò)的實(shí)例,這里的是的真正構(gòu)造函數(shù)最后對(duì)外暴露入口時(shí),將字符與對(duì)等起來(lái)。因此當(dāng)我們直接使用創(chuàng)建一個(gè)對(duì)象時(shí),實(shí)際上是創(chuàng)建了一個(gè)的實(shí)例,這里的正真構(gòu)造函數(shù)是原型中的方法。 showImg(https://segmentfault.com/img/remote/1460000008749398); 早幾年學(xué)習(xí)前端,大家都非常熱衷于研究jQuery源...

    RebeccaZhong 評(píng)論0 收藏0
  • 幾個(gè)例子搞定javascriptthis作用域

    摘要:但是有一個(gè)總的原則,那就是指的是,調(diào)用函數(shù)的那個(gè)對(duì)象。純粹的函數(shù)調(diào)用這是函數(shù)的最通常用法,屬于全局性調(diào)用,因此就代表全局對(duì)象此時(shí)的是作為對(duì)象方法的調(diào)用函數(shù)還可以作為某個(gè)對(duì)象的方法調(diào)用,這時(shí)就指這個(gè)上級(jí)對(duì)象。 函數(shù)this的用法 his是Javascript語(yǔ)言的一個(gè)關(guān)鍵字。 它代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用。比如 function test(){   thi...

    kevin 評(píng)論0 收藏0
  • 100行代碼,輕松搞定文本編輯器草稿箱

    摘要:本文節(jié)選自設(shè)計(jì)模式就該這樣學(xué)使用備忘錄模式實(shí)現(xiàn)草稿箱功能大家都用過(guò)網(wǎng)頁(yè)中的富文本編輯器,編輯器通常都會(huì)附帶草稿箱撤銷等操作。首先創(chuàng)建發(fā)起人角色編輯器類。 本文節(jié)選自《設(shè)計(jì)模式就該這樣學(xué)》1 使用備忘錄模式實(shí)現(xiàn)草稿箱功能大家都用過(guò)網(wǎng)頁(yè)中的富文本編輯器,編輯器通常都會(huì)附帶草稿箱、撤銷等操作。下面用一段代碼來(lái)實(shí)現(xiàn)一個(gè)...

    番茄西紅柿 評(píng)論0 收藏2637

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<