this關(guān)鍵字揭秘

相信大家在學(xué)習(xí)JavaScript的時(shí)候,this關(guān)鍵字總是會(huì)讓大家感到很困惑,下面就來(lái)給大家詳細(xì)的介紹有關(guān)this的一些知識(shí)點(diǎn)。

this

在JavaScript中this總是指向一個(gè)對(duì)象,而具體指向的那個(gè)對(duì)象是在運(yùn)行代碼時(shí)基于函數(shù)的執(zhí)行環(huán)境動(dòng)態(tài)綁定的,而不是函數(shù)在聲明時(shí)的環(huán)境。

this的指向問(wèn)題

在JavaScript中出去特殊的with和eval之外,具體到實(shí)際運(yùn)用中一般包括以下四種情況:
1、作為對(duì)象的方法調(diào)用;
2、作為普通函數(shù)調(diào)用;
3、作為構(gòu)造函數(shù)調(diào)用;
4、Function.prototype.call和Function.prototype.apply的調(diào)用。

1. 作為對(duì)象的方法調(diào)用

當(dāng)一個(gè)函數(shù)當(dāng)作一個(gè)對(duì)象的方法調(diào)用時(shí),this指向該對(duì)象

var obj = {
    name :  'iFuhang',
    getName : function(){
        console.log(this);        // obj
        console.log(this.name);   // iFuhang
    }
}
obj.getName();

2. 作為普通函數(shù)調(diào)用

當(dāng)一個(gè)函數(shù)不被當(dāng)作對(duì)象的方法調(diào)用時(shí),而是當(dāng)作普通的函數(shù)被調(diào)用時(shí),此時(shí)的this指向全局對(duì)象,在瀏覽器中也就是指的window對(duì)象。

window.name = 'smile';
var getName = function(){
    var name = 'iFuhang';
    return this.name;
}
console.log(getName());   // smile

還有一種情況

window.name = 'smile';
var myObject= {
    name : 'iFuhang',
    getName : function(){
        return this.name;
    }
}
var getName = myObject.getName;
console.log(getName());

這種情況下,雖然getName是myObject.getName()賦值給它的,但是此時(shí)的getName仍然是當(dāng)作普通函數(shù)來(lái)調(diào)用的,所以此時(shí)this還是指向window的。在這種情況下,有的時(shí)候會(huì)帶給我們一些不必要的麻煩,比如下面的示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script>
        document.getElementById('app').onclick = function(){
            console.log(this.id);          // app
        var getId = function(){
            console.log(this.id);     // undefined
        }
        getId();
    }
    </script>
</body>
</html>

大家可以看到,最后getId()函數(shù)中打印出來(lái)的是undefined,這個(gè)結(jié)果我想大家并不意外了,是的,getId()仍然是作為一個(gè)普通函數(shù)的調(diào)用。其是我們最后想要的結(jié)果是打印出div的id,那么要怎樣解決呢?
其實(shí)很簡(jiǎn)單,我們可以在執(zhí)行g(shù)etId()函數(shù)之前,先將div的引用保存起來(lái),然后調(diào)用它就可以了。還是來(lái)看代碼吧!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script>
        document.getElementById('app').onclick = function(){
            var self = this;     // 提前將this保存起來(lái),這里的this是指向div的
            console.log(this.id);          // app
        var getId = function(){
            console.log(this.id);     // app
        }
        getId();
    }
    </script>
</body>
</html>

好了,問(wèn)題解決了,是不是很簡(jiǎn)單。其實(shí)這里可以還可以通過(guò)call方法來(lái)改變this的指向,關(guān)于call方法的應(yīng)用我們?cè)诤竺鎸?huì)講述。

需要注意的是在ECMAScript5中的嚴(yán)格模式下,普通函數(shù)的this指向并不是window了。

function getThis(){
    "use strict";
    console.log(this);     // undefined
}
getThis();

3. 作為構(gòu)造函數(shù)的調(diào)用

構(gòu)造函數(shù)看起來(lái)其實(shí)和普通函數(shù)沒(méi)啥區(qū)別,只是在調(diào)用方式上不一樣,當(dāng)使用new運(yùn)算符調(diào)用函數(shù)時(shí),此時(shí)此函數(shù)就稱為構(gòu)造函數(shù),并且總是返回一個(gè)對(duì)象,通常情況下,構(gòu)造函數(shù)中的this指向返回的這個(gè)對(duì)象。

var MyName = function(){
    this.name = 'iFuhang';
}
var obj= new MyName();
console.log(obj.name);    // iFuhang

使用構(gòu)造函數(shù)的時(shí)候,需要注意一個(gè)問(wèn)題,如果構(gòu)造函數(shù)顯式的返回了一個(gè)對(duì)象,此時(shí)的this指向的是返回的這個(gè)對(duì)象了。如果返回的不是一個(gè)對(duì)象,就不會(huì)存在下面這種情況了。

var MyName = function(){
    this.name = 'iFuhang';
    return {
        name : 'smile';
    }
}
var obj= new MyName();
console.log(obj.name);    // smile

4. Function.prototype.call和Function.prototype.apply的調(diào)用

通過(guò)Function.prototype.call和Function.prototype.apply這兩種方法可以動(dòng)態(tài)的修改this的指向。

var obj1 = {
    name : 'iFuhang',
    getName : function(){
        return this.name;
    }
}

var obj2 = {
    name : 'smile'
}

console.log(obj1.getName());    // iFuhang
console.log(obj1.getName.call(obj2));   // smile

點(diǎn)擊了解更多關(guān)于call和apply的知識(shí)點(diǎn)。

以上就是關(guān)于this的四種指向問(wèn)題了,下面講解一下this丟失的問(wèn)題。

this丟失

在開(kāi)發(fā)中經(jīng)常會(huì)遇到this丟失的問(wèn)題,就比如下面這個(gè)示例:

var obj = {
    name : 'iFuhang',
    getName : function(){
        return this.name;
    }
}
console.log(obj.getName());   // iFuhang
var getName = obj.getName();
console.log(getName());    //undefined

出現(xiàn)這種情況的原因其實(shí)之前講到過(guò)的,在調(diào)用getName時(shí),其實(shí)時(shí)普通函數(shù)的調(diào)用方式,所以此時(shí)的this指向window,但是window中并沒(méi)有name這是屬性,所以會(huì)返回undefined,如果在嚴(yán)格模式下,則會(huì)報(bào)錯(cuò)。再來(lái)看看下面這個(gè)例子:

一般我們用JavaScript獲取DOM節(jié)點(diǎn)時(shí)都會(huì)用到document.getElementById等之類的方法,但是為了使用簡(jiǎn)單我們一般會(huì)封裝一個(gè)函數(shù)來(lái)簡(jiǎn)化操。

var getId = function(id){
    return document.getElementById(id);
}
getId(id);

還有人思考為什么不能使用下面的方法呢?不是顯得更加簡(jiǎn)單些嗎?

var getId = document.getElementById;
getId(id);

此段代碼運(yùn)行時(shí)會(huì)拋出一個(gè)錯(cuò)誤。(Uncaught TypeError: Illegal invocation)

這是因?yàn)樵谠S多瀏覽器的引擎中實(shí)現(xiàn)document.getElementById時(shí)都會(huì)用到this,而且this都被期望指向的是document,在getElementById被document調(diào)用的時(shí)候,this確實(shí)時(shí)指向document的,但是當(dāng)用getId來(lái)引用document.getElementById調(diào)用時(shí),此時(shí)的getId是作為普通函數(shù)調(diào)用的,this會(huì)指向window,而不再是document。此時(shí)我們可以通過(guò)apply來(lái)改變this指向document。

document.getElementById = (function(func) {
    return function(){
        return func.apply(document, arguments);
    }
})(document.getElementById );

var getId = document.getElementById;
getId(id);

這段代碼中最后執(zhí)行的其實(shí) func.apply(document, arguments)這個(gè)函數(shù),我們將document.getElementById作為參數(shù)傳遞,也就是func,最后在調(diào)用func時(shí),利用apply將this指向了document,所以最后可以輸出正確結(jié)果了。

閱讀原文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式。簡(jiǎn)單...
    舟漁行舟閱讀 8,140評(píng)論 2 17
  • 在JavaScript編程中,this關(guān)鍵字總是讓初學(xué)者感到迷惑,F(xiàn)unction.prototype.call和...
    白小蟲閱讀 472評(píng)論 0 1
  • 第一部分 準(zhǔn)入訓(xùn)練 第1章 進(jìn)入忍者世界 js開(kāi)發(fā)人員通常使用js庫(kù)來(lái)實(shí)現(xiàn)通用和可重用的功能。這些庫(kù)需要簡(jiǎn)單易用,...
    如201608閱讀 1,411評(píng)論 1 2
  • 單例模式 適用場(chǎng)景:可能會(huì)在場(chǎng)景中使用到對(duì)象,但只有一個(gè)實(shí)例,加載時(shí)并不主動(dòng)創(chuàng)建,需要時(shí)才創(chuàng)建 最常見(jiàn)的單例模式,...
    Obeing閱讀 2,321評(píng)論 1 10
  • 陽(yáng)光明媚獨(dú)品味, 一盅兩件慰勞胃。 飲歌慢調(diào)陶醉人, 有情無(wú)伴亦無(wú)謂。
    康真閱讀 238評(píng)論 0 0

友情鏈接更多精彩內(nèi)容