重學前端之 讓人心態爆炸的this究竟是個什麼玩意

一.前言

兩年前,曾經的組長對我說過,一個前端連閉包原型this都搞不明白,還好意思說本身是前端。以後我一直去試着理解this,看了好多博客和視頻教學,發現好像並非特別好理解。可是在以後的項目中,我都使用了this。在接觸和使用事後,好像對this有點了解,特別寫一篇博客記錄一下關於this的二三事,方便之後查詢,也給剛剛接觸前端的小夥伴一點點幫助前端

二.this是什麼?

首先this在js中理解起來很簡單,他就是當前對象,也能夠理解成指向的對象,那麼問題來了,那麼我怎麼知道當前指的是那個對象?bash

三.this的到底指向的是誰?

首先咱們想理解this的話,咱們必需要理解兩句話
全局變量是window的屬性,函數是window的方法
this誰最後調用,他就是誰閉包

首先咱們理解一下使用代碼理解一下app

let a = '5'
console.log(window.a)  //5
function foo(){
    reutrn 'foo'
}
console.log(window.foo())   //foo
複製代碼

咱們申明瞭一個全局變量a和一個函數foo,可是咱們調用他們的時候並無直接調用,而是使用window這個全局對象調用來調用屬性和方法的方式調用,因此能夠看到打印出他們的值,能夠得出全局變量是window的屬性,函數是window的方法這一結論 而後咱們運行代碼函數

var name = 'Tom'
function name(){
    var name = 'Jerry'
    console.log(this.a)
}
name()  // 'Tom'
console.log(this)   //window
複製代碼

在全局做用域中,函數是window的方法,name函數由window調用,那麼函數內部的this指向的就是window,固然打印出出的this.name固然就是全局做用域下的name值了 簡單瞭解了this的指向,咱們細分一下幾個複雜場景下面的this指向(this究竟是誰)學習

在函數內部嵌套的內部函數

var name = 'apple'
    function fn0(){
        var name = 'Tom'
        function fn1(){
            console.log(this.name);
        }
        fn1();
    }

    fn0();
複製代碼

函數內部嵌套的內部函數,依然指向全局對象(window)ui

在構造函數中和對象中

function Person(name){
        this.name = name;
        this.say = function(){
          console.log('Hello'+this.name)
        }
    }
    Person.prototype.printName = function(){
        console.log(this.name);
    };
    
    var a = new Person('Byron');
    a.say()     //"HelloByron"
    a.printName()   //"Byron"
複製代碼

在構造函數中,this的指向就調用他這個對象的方法,不管是否在原型上this

var name = 'apple'
var obj1 = {
    name: 'Byron',
    fn : function(){
        console.log(this.name);
    }
};
obj1.fn()   //  Byron
複製代碼

在對象中使用也是同樣,this的指向在就是他調用他這個對象上 這裏有個小陷阱,加上代碼看一下spa

var fn2 = obj1.fn;
fn2();  //'apple'
複製代碼

咱們把方法賦值給一個變量,直接用變量調用看看,這個時候咱們就能夠看出來,this的指向改變了,變成全局的了,符合咱們上面的第二句話,this誰最後調用,他就是誰prototype

setTimeout、setInterval

在setTimeout、setInterval的內部函數中,不管是誰調用,他指向的都是全局變量

var name = 'apple'
var obj1 = {
    name: 'Byron',
    fn : function(){
       setTimeout(function(){
           console.log(this.name)
       },300)
       setInterval(function(){
           console.log(this.name+'666')
       },300)
    }
};
ob1.fn()    //apple
            //apple+666
fn1 = obj1.fn
fn1()       //apple
            //apple+666
複製代碼

能夠看得出來,打印的結果能夠得出this指向的都是全局對象window

DOM對象綁定事件

document.querySelector('input') = function(){
    console.log(this.value)
}
複製代碼

DOM對象綁定事件中的函數中的this指向的是當前這個DOM節點

箭頭函數

箭頭函數中,this的指向有點特別:建立時的封閉詞法上下文的this保持一致

var name = 'tom'
var obj1 = {
    name :  'Byron',
    fn :function(){
        setTimeout(()=>{
        console.log(this.name)
      },0)
    }
};
obj1.fn() //'Byron'
複製代碼

因爲箭頭函數特殊的緣由,箭頭函數沒有原型,因此箭頭函數自己沒有this,他只能指向定義外層第一個普通的this,那若是那個普通的this變化了,箭頭函數中的this會指向哪呢?

var name = 'tom'
var obj1 = {
    name :  'Byron',
    fn :function(){
        setTimeout(()=>{
        console.log(this.name)
      },0)
    }
};
var obj2 = {
    name : 'hello world'
}
obj1.fn.call(obj2) //'hello world'
複製代碼

能夠看出若是外層的this變化了,箭頭函數內的this會隨着外層的變化而變化

四.總結

1.this的指向不是固定的,是會變化的(這篇博客尚未講call,apply,bind等函數的用法)
    2.this誰調用他,他就指向誰
    3.在setTimeout、setInterval中,不使用箭頭函數的狀況下this指向全局對象window
    4.箭頭函數沒有原型,this指向外層做用域
複製代碼

五.結語

想要完全瞭解this,必須在項目中多多使用this,遇到問題打印一下,結合網上的博客分析爲何會這樣,這樣學習起來也比較快,理解也能加深,畢竟學習一個東西的最好的方法就是去使用他。若是文中有錯誤,但願你們在評論裏面提出指正,本人加以改正

相關文章
相關標籤/搜索