JS-箭頭函數及其this的指向和改變this指向(call apply bind)


2,箭頭函數
    function(){}        ---   ()=>{}     箭頭函數
    function(e){}       ---   e =>{}     箭頭函數
    function(){一行}    ---   ()=>一行    箭頭函數
    function(e){一行}   ---   e =>一行    箭頭函數

    特點:1,this指向與一般的function函數不同
        聲明式  function fun(){}           this指向,window
        賦值式  var fun = function(){}     this指向,window
        forEach()循環                      this指向,window
        定時器,延時器  setInterval(function(){} , 時間)
                                            this指向,window
        對象中的函數 const obj = {fun:function(){}}
                                            this指向,obj對象
        事件處理函數 標簽.addEventListener(事件類型,function(){})
                                            this指向,標簽對象
                                        
        箭頭函數的this指向,是父級程序的this指向
            如果父級程序有this指向,指向向的就是父級程序的this指向
            如果父級程序沒有this指向(對象,數組是沒有this),指向的是window
        
        2,箭頭函數,無法改變this指向

3,改變this指向
    函數.call(參數1,其他參數...)
        立即執行函數,並且改變函數的this指向為參數1表示的內容
        其他參數,是原始函數的實參,多個實參使用逗號間隔
    函數.apply(參數1,[數組參數])
        立即執行函數,並且改變函數的this指向為參數1表示的內容
        數組參數,是原始函數的參數,多個參數以數組的單元的形式存儲
    函數.bind(參數1)
        不會立即執行函數,而是生成一個新的函數
        新函數,參數,程序內容,都與原始函數相同
        只是this改變為參數1表示的內容

 

一.箭頭函數

所謂的箭頭函數
是函數的另一種語法形式
const fun = function(){}     普通函數
const fun = ()=>{}           箭頭函數
將匿名函數的部分,從 function(){} 寫成 ()=>{} 的形式

如果函數只有一個參數,可以不寫()
const fun = function(e){}     普通函數
const fun = e => {}           箭頭函數

如果執行體中只有一行代碼,可以不寫{}
const fun = e=>{console.log(e)}    普通箭頭函數
const fun = e=> console.log(e)     不寫{}箭頭函數


const oDiv = document.querySelector('div');

// 普通函數
oDiv.addEventListener('click' , function(){
    console.log('我是div標簽')
})

// 箭頭函數
oDiv.addEventListener('click' , ()=>{
    console.log('我是div標簽');
})

// 只有一個參數,可以不寫(),直接定義一個參數
oDiv.addEventListener('click' , e=>{
    console.log(e);
})

// 只有一行代碼,不寫{}
oDiv.addEventListener('click' , e=>console.log(e) )

二.箭頭函數的this指向

箭頭函數中的this指向
為什么要有箭頭函數?
是為了配合明天要講的面向對象和構造函數
在箭頭函數中,this指向有特殊的意義,專門可以用來配合構造函數和面向對象編程思想

在箭頭函數中,this指向,父級程序的this指向
如果父級程序有this指向,那么箭頭函數指向的就是父級程序的this
如果父級程序沒有this指向,那么指向的就是window

關於this的總結
1,普通的function函數
    聲明式 --- window
    賦值式 --- window
    forEach循環 --- window
    定時器,延時器 --- window
    對象中的函數 --- 對象本身
    事件綁定事件處理函數 --- 綁定事件的標簽

2,箭頭函數的this指向
    父級程序的this指向
    如果父級程序有this指向(父級程序也是函數),this指向的就是父級程序的this指向
    如果父級程序沒有this指向(數組,對象....),this指向的是window

復習this指向

***************普通函數的this指向**************
聲明式,賦值式/匿名函數,對象中函數,綁定的事件處理函數
this都是指向的調用函數時,之前定義的內容

1,聲明式 --- 指向的是window
function fun1(){
    console.log(this);
}

fun1();

2,匿名函數/賦值式 --- 指向的是window
const fun2 = function(){
    console.log(this);
}
fun2();

3,定義在對象中的函數 --- 指向的是對象
const obj = { 
    fun3 : function(){
        console.log(this);
    }
}
obj.fun3();

4,綁定的事件處理函數 --- 指向的是綁定事件處理函數的標簽
const oDiv = document.querySelector('div');
// oDiv.onclick = function(){
//     console.log(this);
// }

oDiv.addEventListener('click' , function(){
    console.log(this);
})


*******************箭頭函數的this指向********************
與普通函數的this指向是有區別的
箭頭函數中,this的指向是父級程序的this指向
當前的程序,箭頭函數的父級程序,
如果沒有,則this指向的就是window

oDiv.addEventListener('click' , ()=>{
    console.log(this);
})

// 對li進行操作
const oLis = document.querySelectorAll('li');
oLis.forEach(function(item,key){
    // console.log(this);  // 輸出的是forEach的函數的this指向
    // 箭頭函數的this,是父級程序,forEach()的this,是window
    item.addEventListener('click' , ()=>{
        // console.log(key,this);
    })
})

forEach()中 函數的this指向,就是window
const arr = [1,2,3,4,5,6];
arr.forEach(function(){
    console.log(this);
})


const obj = {
    // 普通函數,this指向對象
    fun1 : function(){console.log(this)},
    // 箭頭函數this指向是,父級程序
    // 父級程序是對象
    // 只有函數有this,obj對象沒有this
    // 父級程序沒有this,指向的是window
    fun2 : ()=>{console.log(this)},

    // fun3是一個普通函數,this指向的是obj對象
    fun3 : function(){
        // fun4,是一個箭頭函數,this指向的是父級程序的this指向
        // 父級程序是fun3,fun3的this是對象,fun4箭頭函數的this也是對象
        const fun4 = ()=>{console.log(this)};
        fun4();
    }
}
obj.fun1();
obj.fun2();
obj.fun3();

三.改變this指向

重點:箭頭函數,不能改變this指向,只有普通function函數,能改變this指向

改變this指向的方法

1, call()方法
語法: 函數.call(參數1,其他參數....可以是多個或者沒有 )
作用: 調用並且執行函數,同時,將函數的this指向,定義為指定的內容(參數1)
        參數1,是改變的this的指向
        其他參數,是原始函數的實參,原始函數有幾個形參,此時就要對應的輸入幾個實參,沒有形參,就沒有實參

2, apply()方法
語法: 函數.apply(參數1,參數2)  只有兩個參數
        參數1:改變的this的指向內容
        參數2:原始函數的實參,必須是一個數組的形式,將實參定義成數組的單元
其他用法和作用於 .call是相同的

總結: call方法與apply方法,作用,效果,都是完全一致的
        只是對於原始函數的參數賦值方法,不同
        call方法是通過其他多個參數來實現
        apply方法是通過一個數組參數,來實現
        兩個方法沒有本質的區別,愛用哪個用那個

3, bind()方法
語法: const 變量 = 函數.bind(參數1);
不是立即執行函數(下一篇博客有介紹 立即執行函數)
生成一個新的函數,這個新的函數是改變this指向之后的新的函數
參數1,定義的要改變的的this指向
其他參數,一般不定義,是使用函數原有的形參

總結:
    call apply 都是立即執行函數
        參數1,都是改變的this指向
        其他參數,是原始函數的形參(可以有,也可以沒有)
    bind 不是立即執行函數,是生成一個新的函數
        參數1,是改變的this指向
        就使用原始函數的形參


const obj1 = {
    name:'張三',
    age:18,
    sex:'',
}

const obj2 = {
    name:'李四',
    fun2 : function(){
        console.log(this);
    }
}
// 對象中的函數,this指向的是這個對象,obj2
obj2.fun2();
// 改變this指向,指向的是obj1這個對象
// 代用,並且執行fun2這個函數,同時將fun2的this指向,從原始的obj2,改變為obj1
obj2.fun2.call(obj1);

// 帶有參數的函數,this指向的改變

// 定義的帶有參數的普通函數
function fun3(name,age,sex){
    console.log(name,age,sex,this);
}
// 執行時,輸出實參,此時this指向是window
fun3('張三',18,'');

// 改變this指向 , call方法
fun3.call(obj1,'李四',20,'');

// 改變this指向 , apply方法
fun3.apply(obj1 , [ '王五' , 20 , '不知道' ])

// bind方法,不是立即執行函數,而是定義生成一個新的函數
// 新生成的函數,this指向是參數1
// 新生成的函數,形參是原始函數fun3的形參
const fun4 = fun3.bind(obj1);

fun4('王二麻子' , 100 , '不詳');

四.注意事項特別說明

面向對象和面向過程

從面向過程,改造成面向對象
1,獲取的數據,標簽對象,要以參數的形式,定義給構造函數和實例化對象
    獲取標簽對象時,一般獲取父級,傳參父級,在構造函數中,通過父級標簽,獲取子級標簽獨享
2,必須非常非常非常注意 this的指向,一般在面向對象中 都是使用箭頭函數
    如果萬一不能清楚地知道this指向,可以先輸出 this
3,其他步驟和思路基本相同,沒有區別

總結:
1,改不改箭頭函數,看內部是否需要 指向實例化對象的this 
    如果需要,可以改箭頭函數,或者是提前存儲this指向
    如果不許需要,改不改箭頭函數都行
    一切以實現程序為最終需求,程序能執行就可以
2,之前面向過程的是參數,數據等,
    現在是面向對象編程,要在對象的屬性中,定義參數數據
    也就是通過 構造函數 this.屬性 = 屬性值 語法來定義需要獲取的參數數據
3,定義在構造函數方法中的一些變量數據,並不是定義在實例化對象中的屬性
    沒有必須寫成 this.屬性 = 屬性值 的形式
    只要寫成普通的變量定義即可 
    使用時,也是直接使用變量,不需要添加this
4,在構造函數的方法中,調用其他的函數方法
    語法形式 應該是 實例化對象.函數方法名稱()
    在構造函數中,使用this來指向實例化對象,寫成 this.函數方法名稱()

 

轉載: https://blog.csdn.net/DcTbnk/article/details/105419682


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM