ES6箭頭函數(二)-this綁定

箭頭函數,除了幫助我們簡寫之外,最大的好處就是this不再被綁定在調用者,而是繼承與環境對象,在哪個環境定義,this就是指的哪個環境對象。

在編寫構造函數或者函數時,this的指向經常會變化,導致this.屬性無法在各個函數體面使用

案例代碼:

    function Counter() {
        console.log('我是構造體'+this);
        this.number = 0;
​
        //返回一個 ID(數字),可以將這個ID傳遞給 clearTimeout() 來取消執行。        
        this.timer = window.setTimeout(function () {
            this.number++;
            //此時的this的意思是window,window是沒有number屬性的
            console.log(this.number);
        },1000)
    }
​
    var b = new Counter();
    console.log(b.number);
    結果 0
         NaN

爲了解決this指向問題,我們可以使用bind來改變,不能使用call,apply

    function Counter() {
        this.number = 0;
        var fn = function () {
           this.number++
            console.log(this.number);
        }
        // 不能用call、applay,這兩種方法都是立即執行,並且不會循環執行
        // var timer =  window.setTimeout(fn.call(this),3000)
        //var timer =  window.setInterval(fn.apply(this),3000)
        var timer =  window.setInterval(fn.bind(this),3000)
    }
​
    var b = new Counter();
    console.log(b.number);

從上可以看出,想改變this的指向非常困難

有了箭頭函數之後,一切都變得簡單,不在綁定this的指向了

    function Counter() {
        this.number = 0;
        var timer = setInterval(() => {
            console.log(this);
            this.number++;
            console.log(this.number);
        },2000)
    }
​
    var b = new Counter();

原理分析:

普通函數,this的概念是:this是JavaScript的一個關鍵字,他是指函數執行過程中,自動生成的一個內部對象,是指當前的對象,只在當前函數內部使用。(this對象是在運行時基於函數的執行環境綁定的:在全局函數中,this指向的是window;當函數被作爲某個對象的方法調用時,this就等於那個對象)。

 

函數中this對象的取值,是在函數被調用執行的時候確定的。此時會創建執行上下文環境。

對於箭頭函數,它沒有自己的this,不能用作構造函數。

箭頭函數中的this對象是定義時所在的對象,不是調用時所在的對象。

案例1

    var testObject = {
        name:'123',
        sayHi:function () {
            console.log(this);
            // return function () {
            //     console.log(this);
            // }
            //箭頭函數的this,不再是誰調用就是誰,而是指當前環境的this是誰,
            //一般是指父級,因爲箭頭函數沒有this對象,都是從父級繼承過來的
            return ()=>{
                console.log(this);
            }
        }
    }
​
    var hh = testObject.sayHi();
    window.hh();

案例2

    function foo() {
        setTimeout(function() {
            console.log('setTimeout普通函數的this='+this);
            console.log("id: ",this.id);
        }, 100);
    }
    function fooa() {
        setTimeout(()=>{
            console.log('setTimeout箭頭函數的this='+this);
            console.log("id: ",this.id);
        }, 100);
    }
    var id=21;
    //兩個函數的結果都是一樣的:window,21
    //因爲可以理解爲都是由window調用的window.foo() 和 window.fooa()
    foo();  //this指向window對象, 21
    fooa(); //this指向window對象, 21
​
    =========================================
    //setTimeout(普通函數體)的this指向的調用時對象,那麼這個對象如果不改變的話永遠都是window.
    foo.call({id:42}); //this指向window對象, 21
   //setTimeout(箭頭函數體)本身沒有this,定義時對象,也就是哪個對象調用了,this就是哪個對象的
    fooa.call({id:42}); //this指向object對象, 42
​

案例3-返回值是函數的,函數體裏面的this指向的是window,和普通函數裏面的this一樣

const test = {
  name: 'test object',
  createAnonFunction: function() {
    return function() {
      //function 當做了普通函數,this的指向是window
      console.log(this.name);
      console.log(arguments);
    };
  },
 
  createArrowFunction: function() {
    return () => {
      //箭頭函數本身沒有this對象,this是在定義是去找,本身沒有的話,就會去父級尋找
      //當test對象去調用方法createArrowFunction,this就獲得了test對象
      console.log(this.name);
      console.log(arguments);
    };
  }
};
//結果
JavaScript 代碼:
> const anon = test.createAnonFunction('hello', 'world');
> const arrow = test.createArrowFunction('hello', 'world');
 
> anon();
undefined
{}
 
> arrow();
test object
{ '0': 'hello', '1': 'world' }

案例4-函數作爲參數的時候,函數體裏面的this指向的是window,和普通函數裏面的this一樣

    Array.prototype.myFind = function (index,callback) {
        //this是對象數組
        console.log(this)
        for (var i = 0; i < this.length; i++) {
            if(i === index){
                callback(this[i])
            }
        }
    }
    var arr = ['hello', 'WORLD', 'Whatever'];
    arr.myFind(1,function (item) {
        //this是window
        console.log(this);
        console.log(item);
    })
特殊的案例
 Array.prototype.myFind = function (index, callback) {
​
        for (var i = 0; i < this.length; i++) {
            if (i === index) {
                callback.call(this,this[i])
                //callback(this[i])
            }
        }
    }
 
    var arr = ['hello', 'WORLD', 'Whatever'];
    arr.myFind(1, function (item) {
        //array數組
        console.log(this);
​
    })
​
    arr.myFind(1, item => {
        //window對象
        console.log(this);
    })
   
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章