天天看點

簡單學習Es6中的this指向前言更改this指向(面試經常問到)

前言

對于一個前端初學者來說,this的指向是一個必須要掌握的知識點,尤其是es6之後的this指向更加變得飄忽不定,我們今天就來了解一下各種情況下this的指向。

什麼是this

首先,this不是一個函數也不是某個對象,它具體指向什麼東西取決于我們在哪裡去調用這個this,隻有函數調用的時候才會發生this的綁定

1.全局作用域

console.log(this === window) //true

當我們在全局作用域中調用的時候,this指向的是window對象,相當于window調用的這個tihs

2.純函數調用

function fun(){
     console.log(this)//this指向window
 }
 
 fun()           

複制

為什麼在函數體内this也是指向的window,我們可以看到是在全局調用的fun函數,當我們調用的時候會進行預設綁定,也就是綁定到window上。

3.作為對象方法和對象的屬性值

var Person = {
    name:'張三',
    that:this,
    age:function(){
        console.log(this)//Person對象
        console.log(this.name)//李四
    }
}
console.log(Person.that) //window 類似純函數調用
Person.age() //調用對象的age方法            

複制

簡單學習Es6中的this指向前言更改this指向(面試經常問到)

當我們把this作為對象的某個方法去調用的時候,this指向的是這個對象,相當于這個對象調用這個方法

var Person = {
    obj:{
        name:'李四',
        sex:function(){
            console.log(this)//obj對象
        }
    }
}

Person.obj.sex()//調用penson對象中的obj對象的sex方法           

複制

嵌套對象的時候this的指向同樣是誰調用指向誰,這時候是obj對象調用的

簡單學習Es6中的this指向前言更改this指向(面試經常問到)

4.構造函數中的this

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

var obj = new fun('李四',20)

console.log(obj)//控制台列印如下           

複制

這時候的this指向的是構造函數所建立出來的obj對象

簡單學習Es6中的this指向前言更改this指向(面試經常問到)

5.class類中的this

class Person {
        constructor(name){
            this.name = name
            this.say = function () {
                console.log('my name is '+ this.name)
            }
        }

        sleep = function(){
            console.log(this)
        }
    }
    var objA = new Person('李四')
    objA.say()//調用objA對象的say方法 控制台列印 ‘my name is 李四’
    objA.sleep()//調用objA對象的sleep方法 列印 objA對象           

複制

在class中的this都是指向這個構造函數生成的對象

簡單學習Es6中的this指向前言更改this指向(面試經常問到)

6.es6中的箭頭函數this指向

var obj = {
        name:'張三',
        say:()=>{
            console.log(this)
        }
    }
    obj.say()//控制台列印window           

複制

箭頭函數沒有自己的this 會預設繼承父級執行上下文的this,這裡的上下文this就是window

注:當函數執行時,會建立一個稱為執行上下文的内部對象(可了解為作用域)。一個執行上下文定義了一個函數執行時的環境。對象是沒有執行上下文的。

--

var obj = {
        name:'李四',
        person:function() {
          return {
                name:'張三',
                say:()=>{
                    console.log(this)
                }
            }
        }

    };

    obj.person().say()//調用say方法這裡的this指向的是obj對象,箭頭函數沒有this會向上查找。普通函數建立時會綁定this,如果person函數也是箭頭函數的話this指向window           

複制

簡單學習Es6中的this指向前言更改this指向(面試經常問到)
簡單學習Es6中的this指向前言更改this指向(面試經常問到)

更改this指向(面試經常問到)

var Person = {
    name:'張三',
    say:function(age){
       console.log(`my name is ${this.name},i am ${age} years old`)//es6文法模闆字元串
    }
}

var obj = {
   name:'李四'
}           

複制

直接調用

Person.say()

簡單學習Es6中的this指向前言更改this指向(面試經常問到)

bind()

Person.say.bind(obj,'20','第二個參數',...)()//bind傳回的是一個重新綁定this的函數需要調用
Person.say.bind(obj)('20','第二個參數',...)//兩種傳參方式,參數依次加在後面           

複制

簡單學習Es6中的this指向前言更改this指向(面試經常問到)

call

Person.say.call(obj,'20','第二個參數',...)//call傳回的是重新綁定this并且立即調用之後的結果,參數依次加在後面           

複制

簡單學習Es6中的this指向前言更改this指向(面試經常問到)

apply

Person.say.apply(obj,['20','第二個參數'])//傳回的同樣是綁定了this并且立即調用之後的結果,參數是數組格式           

複制

總結:

bind 跟 call和apply相比 差別顯而易見,傳回的結果不同 需要自己去調用,那麼call跟apply有什麼差別呢?其實除了傳參方式不同并沒有很大的差別,有傳聞apply對記憶體的消耗更小一點,因為基本資料類型和引用資料類型在記憶體中存放的方式不同,具體是不是還需要去驗證一番。

本文為作者原創,手碼不易,允許轉載,轉載後請以連結形式說明文章出處。