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

資訊專欄INFORMATION COLUMN

Know this, use this! (總結(jié) this 的常見用法)

zorro / 1937人閱讀

摘要:而當(dāng)做普通函數(shù)調(diào)用的話,實(shí)際上即第種情況下,對(duì)函數(shù)普通調(diào)用,此時(shí)的指向這是正常情況下,會(huì)正確返回并且指向該對(duì)象,但是在構(gòu)造函數(shù)當(dāng)中,如果返回了一個(gè)對(duì)象,那么會(huì)指向返回的那個(gè)對(duì)象。

this應(yīng)該是一個(gè)討論了很久的話題了。其中,關(guān)于this的文章,在很多的博客當(dāng)中也有很多介紹,但是,以前我都是一知半解的去了解它,就是看博客當(dāng)中,只介紹了一些情況下的 this 的使用方式,但是也并沒有自己去做過總結(jié)。剛好是在掘金當(dāng)中有看到一篇關(guān)于this的一些詳細(xì)文章,文末會(huì)附上鏈接以及英文原文,這里純粹是自己進(jìn)行一個(gè)總結(jié),以后方便自己進(jìn)行回顧以及加深印象。希望這篇文章對(duì)于你了解this有一定的幫助,文末還有一些練習(xí)題噢~希望真的對(duì)你們有幫助。(因?yàn)閷戫?xiàng)目過程中,一直被 this 坑過,卻找了很久的 bug ,我真是 樂了狗)

在了解this之前,相信大家都應(yīng)該會(huì)知道作用域這個(gè)知識(shí)點(diǎn)的存在,函數(shù)在創(chuàng)建之后,會(huì)構(gòu)建自己的執(zhí)行環(huán)境以及作用域,這是一開始就確定了。但是實(shí)際的上下文(context)環(huán)境,也可以理解為就是this,它是動(dòng)態(tài)確定的,即在函數(shù)運(yùn)行時(shí)才確定this所指向的對(duì)象,而非聲明時(shí)所指向的對(duì)象。

關(guān)于this,總結(jié)起來,主要有以下幾個(gè)途徑能夠被運(yùn)用到。

1 對(duì)象方法中調(diào)用this

如果函數(shù)被當(dāng)中對(duì)象的一個(gè)方法進(jìn)行調(diào)用,則this值指向該對(duì)象。

var person = {
    name: "Alice",
    sayName: function() {
        alert("welcome " + this.name);
    }
}

person.sayName();    // this == person, alert: "welcome Alice"

在這里,函數(shù)的this指向該對(duì)象(即 person);但是有一點(diǎn)需要注意,就是當(dāng)對(duì)象的方法被賦予給一個(gè)變量時(shí),其則變?yōu)榱撕瘮?shù)觸發(fā),此時(shí)的this為 window 或者 undefined(嚴(yán)格模式下),如下:

var name = "Bob";
var person;    // 即上面的定義,此不拓展詳細(xì),直接使用

var say = person.sayName;    // this == window || undefined
say();    // "welcome Bob" || throw an error: Cannot read property "name" of undefined(...)
2 函數(shù)內(nèi)部使用

在函數(shù)內(nèi)部當(dāng)中使用了 this,即函數(shù)被當(dāng)做方法使用,不同于 1 當(dāng)中作為對(duì)象的方法使用,此時(shí)調(diào)用,是在全局作用域下進(jìn)行調(diào)用,即在window下進(jìn)行調(diào)用,由定義可以知道,在全局作用域下聲明一個(gè)函數(shù),其自動(dòng)加為window的一個(gè)屬性。this此時(shí)名正言順的會(huì)指向window,嚴(yán)格模式下為 undefined

function sayThis() {
    alert(this == window);    // true
}

結(jié)合第一點(diǎn),函數(shù)作為對(duì)象的一個(gè)方法使用,這里存在一個(gè)小坑,即閉包,啥是閉包,這個(gè)在這里就不扯開了,最簡(jiǎn)單的理解就是 Function that returns function,如果不理解什么是閉包的話,可以去翻翻 《JavaScript 高級(jí)程序設(shè)計(jì)》第七章關(guān)于閉包的相關(guān)內(nèi)容。第一點(diǎn)當(dāng)中存在一個(gè)小坑,就是將對(duì)象的方法賦予給一個(gè)變量的時(shí)候,其變?yōu)楹瘮?shù)觸發(fā),此時(shí)的 this 實(shí)際上是指向 window(非嚴(yán)格模式)。

那么,當(dāng)函數(shù)中返回一個(gè)函數(shù),此時(shí)在對(duì)象當(dāng)中調(diào)用該方法,其就相當(dāng)于是函數(shù)觸發(fā),此時(shí)的 this,在不做任何上下文綁定的前提之下,其指向 window(非嚴(yán)格模式)。

var name = "Bob",
    person = {
        name: "Alice",
        sayName: function() {
            console.log(this === person);    // true
            return function() {
                console.log(this === person);    // false
                console.log(this === window);    // true
                console.log(this.name);          // Bob
            };
        }
    };

person.sayName()();

當(dāng)然,要解決這個(gè)問題的方法,很簡(jiǎn)單,就是給他綁定一個(gè)上下文。

var name = "Bob",
    person = {
        name: "Alice",
        sayName: function() {
            console.log(this === person);    // true
            return function() {
                console.log(this === person);    // true
                console.log(this === window);    // false
                console.log(this.name);          // Alice
            }.bind(this);
        }
    };

person.sayName()();
3 new 當(dāng)中進(jìn)行使用

我們知道在使用 new 方法創(chuàng)建對(duì)象的時(shí)候,會(huì)經(jīng)過如下這些個(gè)過程:

創(chuàng)建對(duì)象,將 this 值賦予新的對(duì)象

調(diào)用構(gòu)造函數(shù),為 this 添加屬性和方法

返回 this 給當(dāng)前的對(duì)象

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

var person1 = new Person("Alice", 29);
console.log(person1.name);    // Alice

這里要記得使用 new 運(yùn)算符,否則,其只能算是普通的調(diào)用,而不是創(chuàng)建一個(gè)新的實(shí)例對(duì)象。而當(dāng)做普通函數(shù)調(diào)用的話,實(shí)際上即 第 2 種情況下,對(duì)函數(shù)普通調(diào)用,此時(shí)的 this 指向 window

function Person(name, age) {
    this.name = name;
    this.age = age;
    return this;
}

var person1 = Person("Alice", 29);
console.log(person1.name);    // Alice
console.log(window.name);     // Alice
console.log(person1 === window);    // true

這是正常情況下,this 會(huì)正確返回并且指向該對(duì)象,但是在構(gòu)造函數(shù)當(dāng)中,如果返回了一個(gè)對(duì)象,那么 this 會(huì)指向返回的那個(gè)對(duì)象。

function Person(name, age) {
    this.name = name;
    this.age = age;
    return {
        name: "Bob"
    };
}

var person1 = new Person("Alice");
console.log(person1.name);    // Bob
console.log(person1.age);     // undefined

題外話,類似的,聯(lián)想到 var a = new Person(),則 a instanceof Person一定返回 true嗎?留給你們想一想咯。

4 使用 callapplybind 改變 this

在引用類型 Function當(dāng)中,函數(shù)存在兩個(gè)方法屬性,callapply,在 ECMAScript5當(dāng)中,加入了 bind 方法。題外話,他們?nèi)邊^(qū)別,應(yīng)該都知道了吧,不知道的加緊補(bǔ)習(xí)呀。

var name = "Bob";
var person = {
    name: "Alice",
    age: 29
}

function sayName() {
    console.log(this.name);
}

sayName.call(person);    // Alice

這里是使用了 call 方法來改變了 this的執(zhí)行環(huán)境,至于使用 apply,效果一樣,只是二者差別在于傳入?yún)?shù)的不同。

func.call(context, arg1, arg2, ...)
func.apply(context, [arg1, arg2, ...])

使用 bind 方法進(jìn)行上下文的改變,bind 方法與 callapply有著本質(zhì)的不同,其不同點(diǎn)是,bind()函數(shù)返回的是一個(gè)新的函數(shù),即方法,而后兩者則都是立即執(zhí)行函數(shù),使用的時(shí)候即調(diào)用了該函數(shù),返回方法操作的結(jié)果。

并且,使用 bind()方法創(chuàng)建的 上下文,其為永久的上下文環(huán)境,不可修改,即使是使用 call 或者 apply方法,也無法修改 this 所指向的值。

var name = "Bob";
var person = {
    name: "Alice",
    age: 29
}

function sayName() {
    console.log(this.name);
}

var say = sayName.bind(person);
say();        // Alice
sayName();    // Bob
5 箭頭函數(shù)

箭頭函數(shù)并不創(chuàng)建其自身的上下文,其上下文 this,取決于其在定義時(shí)的外部函數(shù)。

并且,箭頭函數(shù)擁有靜態(tài)的上下文,即一次綁定之后,便不可再修改,即使是用了 第 4 種用途當(dāng)中的改變上下文的方法,也不為之動(dòng)容。

var num = [1, 2, 3];

(function() {
    var showNumber = () => {
        console.log(this === num);    // true
        console.log(this);            // [1, 2, 3]
    }
    console.log(this === num);        // true
    showNumber();                     // true && [1, 2, 3]
    showNumber.call([1, 2]);          // true && [1, 2, 3]
    showNumber.apply([1, 2]);         // true && [1, 2, 3]
    showNumber.bind([1, 2])();        // true && [1, 2, 3]
}).call(num);

由于箭頭函數(shù)的外部決定上下文以及靜態(tài)上下文等的特性,不太建議使用箭頭函數(shù)在全局環(huán)境下來定義方法,因?yàn)椴荒芡ㄟ^其他方法改變其上下文。這很蛋疼。

function Period (hours, minutes) {  
    this.hours = hours;
    this.minutes = minutes;
}
Period.prototype.format = () => {  
    console.log(this === window);    // => true
    return this.hours + " hours and " + this.minutes + " minutes";
};
var walkPeriod = new Period(2, 30);  
console.log(walkPeriod.hours);
walkPeriod.format();    // => "undefined hours and undefined minutes"

此時(shí)的 this 實(shí)際上是指向了 window,所以 this.hours 和 this.minutes實(shí)際上沒有聲明的,故為 undefined。

在全局環(huán)境下,還是選用 函數(shù)表達(dá)式 來進(jìn)行函數(shù)的定義,可以保證正確的上下文環(huán)境

function Period (hours, minutes) {  
    this.hours = hours;
    this.minutes = minutes;
}
Period.prototype.format = function() {  
    console.log(this === walkPeriod);    // => true
    return this.hours + " hours and " + this.minutes + " minutes";
};
var walkPeriod = new Period(2, 30);  
walkPeriod.format(); // "2 hours and 30 minutes"
練習(xí)
// 練習(xí)1
var func = (function(a) {
    this.a = a;
    return function(a) {
        a += this.a;
        return a;
    }
})(function(a, b) {
    return a;
}(1, 2))

func(4) // ?

// 練習(xí)2
var x = 10,
    foo = {
        x: 20,
        bar: function() {
            var x = 30;
            return this.x;
        }
    }

console.log(foo.bar());
console.log((foo.bar)());
console.log((foo.bar = foo.bar)());
console.log((foo.bar, foo.bar)());

希望看完這篇文章,這兩個(gè)練習(xí)題,你是能夠做出來的呀~ 好好分析一下唄。如果不確定的話,可以在留言板上,咱們相互討論一下呀~

參考

JavaScript This之謎 (第二個(gè)參考的譯文)

Gentle explanation of "this" keyword in JavaScript

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

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

相關(guān)文章

  • JavaScript 原型系統(tǒng)變遷,以及 ES6 class

    摘要:一般我們對(duì)這種構(gòu)造函數(shù)命名都會(huì)采用,并把它稱呼為類,這不僅是為了跟的理念保持一致,也是因?yàn)榈膬?nèi)建類也是這種命名。由生成的對(duì)象,其是。這是標(biāo)準(zhǔn)的規(guī)定。本文的主題是原型系統(tǒng)的變遷,所以并沒有涉及和對(duì)原型鏈的影響。 概述 JavaScript 的原型系統(tǒng)是最初就有的語(yǔ)言設(shè)計(jì)。但隨著 ES 標(biāo)準(zhǔn)的進(jìn)化和新特性的添加。它也一直在不停進(jìn)化。這篇文章的目的就是梳理一下早期到 ES5 和現(xiàn)在 ES6,...

    chuyao 評(píng)論0 收藏0
  • 快速掌握J(rèn)avaScript面試基礎(chǔ)知識(shí)(二)

    摘要:第一部分請(qǐng)點(diǎn)擊快速掌握面試基礎(chǔ)知識(shí)一閉包閉包由一個(gè)函數(shù)以及該函數(shù)定義是所在的環(huán)境組成。當(dāng)匿名函數(shù)執(zhí)行的時(shí)候,的值為。這個(gè)問題可以改用后面會(huì)介紹方法來解決,通過對(duì)每一個(gè)匿名函數(shù)構(gòu)建獨(dú)立的外部作用域來實(shí)現(xiàn)。 譯者按: 總結(jié)了大量JavaScript基本知識(shí)點(diǎn),很有用! 原文: The Definitive JavaScript Handbook for your next develope...

    fyber 評(píng)論0 收藏0
  • [翻譯]You Don't Know JS: this & Object Prot

    摘要:引用是從匿名函數(shù)內(nèi)部引用自身的唯一方法,不過,最好的方法是避免使用匿名函數(shù),至少在那些需要引用自身的時(shí)候,使用命名函數(shù)或者表達(dá)式。 [翻譯]Chapter1 this or that 第一次翻譯,翻譯的不好,已經(jīng)再盡全力s去翻譯了,如果哪里看不明點(diǎn),請(qǐng)出門左轉(zhuǎn)下邊原文地址 英文原文點(diǎn)擊這里 javascript中最令人困惑的東西就是this關(guān)鍵字,它在每個(gè)函數(shù)作用域中都會(huì)自動(dòng)定義的一個(gè)...

    mingzhong 評(píng)論0 收藏0
  • 魔幻語(yǔ)言 JavaScript 系列之 call、bind 以及上下文

    摘要:那么,它到底是如何工作的呢讓我們從一種更簡(jiǎn)單的實(shí)現(xiàn)開始實(shí)際上這種實(shí)現(xiàn)代碼更短,并且更易讀是函數(shù)原型中的一個(gè)函數(shù),它調(diào)用函數(shù),使用第一個(gè)參數(shù)作為參數(shù),并傳遞剩余參數(shù)作為被調(diào)用函數(shù)的參數(shù)。 原文:The Most Clever Line of JavaScript 作者:Seva Zaikov 原文 最近 一個(gè)朋友 發(fā)給我一段非常有趣的 JavaScript 代碼,是他在某個(gè) 開源庫(kù)中...

    cuieney 評(píng)論0 收藏0
  • 《You Don't Know JS》閱讀理解——this

    摘要:運(yùn)行規(guī)則根據(jù)的運(yùn)作原理,我們可以看到,的值和調(diào)用棧通過哪些函數(shù)的調(diào)用運(yùn)行到調(diào)用當(dāng)前函數(shù)的過程以及如何被調(diào)用有關(guān)。 1. this的誕生 假設(shè)我們有一個(gè)speak函數(shù),通過this的運(yùn)行機(jī)制,當(dāng)使用不同的方法調(diào)用它時(shí),我們可以靈活的輸出不同的name。 var me = {name: me}; function speak() { console.log(this.name); }...

    tianren124 評(píng)論0 收藏0

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

0條評(píng)論

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