js中call、apply、bind

call apply bind都有著改變this指向的功能,什么叫改變this指向呢?this:當(dāng)前作用域的頂層對象。某個方法內(nèi)可能引用了他當(dāng)前作用域的對象的屬性,改變this指向就是把他的this更換為其他對象。這么做的意義是什么呢?話不多說,上代碼。

    const Animal = {
        name: '動物',
        say() {
            console.log(`大家好,我是${this.name}`)
        }
    }


    const Cat = {
        name: '大貍貓'
    }


    Animal.say.call(Cat)
    // 大家好,我是大貍貓

    Animal.say.apply(Cat)
    // 大家好,我是大貍貓
    
    Animal.say.bind(Cat)()
    // 大家好,我是大貍貓

上圖三個方法都能通過傳參改變Animal.say方法中的this。call apply bind都是Function.prototype上的方法,通過傳參的方式把內(nèi)部this替換為參數(shù)中的對象。來看區(qū)別,為什么bind后面還跟了個括號?括號表示調(diào)用,逆向思考可以得知,bind方法返回了一個新的函數(shù),手動執(zhí)行才能調(diào)用。callapply都是直接調(diào)用。bind寫法雖然看上去麻煩點,但如果你此時不想調(diào)用而是在未來的某一刻調(diào)用,這個時候就可以賦值給一個變量,等到需要的時候再調(diào)用了

    const Animal = {
        name: '動物',
        say(food, sport) {
            console.log(`大家好,我是${this.name}, 我喜歡吃${food},我喜歡的運(yùn)動是${sport}`)
        }
    }


    const Cat = {
        name: '大貍貓'
    }


    Animal.say.call(Cat, '貓草', '抓老鼠')
    // 大家好,我是大貍貓, 我喜歡吃貓草,我喜歡的運(yùn)動是抓老鼠

    Animal.say.apply(Cat, ['貓草', '抓老鼠'])
    // 大家好,我是大貍貓, 我喜歡吃貓草,我喜歡的運(yùn)動是抓老鼠

    Animal.say.bind(Cat)('貓草', '抓老鼠')
    // 大家好,我是大貍貓, 我喜歡吃貓草,我喜歡的運(yùn)動是抓老鼠

可以看出,額外參數(shù)都緊跟在第一個參數(shù)之后,callbind參數(shù)以散列形式,apply參數(shù)以數(shù)組形式,并推理出apply擁有打散數(shù)組的功能

    const Animal = {
        name: '動物',
        say(food, sport) {
            console.log(`大家好,我是${this.name}, 我喜歡吃${food},我喜歡的運(yùn)動是${sport}`)
        }
    }

    const Cat = {
        name: '大貍貓'
    }

    Animal.say.bind(Cat)('貓草', '抓老鼠')
    // 大家好,我是大貍貓, 我喜歡吃貓草,我喜歡的運(yùn)動是抓老鼠
    
    Animal.say.bind(Cat, '貓草1')('貓草', '抓老鼠')
    // 大家好,我是大貍貓, 我喜歡吃貓草1,我喜歡的運(yùn)動是貓草

    Animal.say.bind(Cat, '貓草1', '抓老鼠1')('貓草', '抓老鼠')
    // 大家好,我是大貍貓, 我喜歡吃貓草1,我喜歡的運(yùn)動是抓老鼠1

以上代碼可以看出,bind方法產(chǎn)數(shù)傳遞,如果bind方法內(nèi)有參數(shù)以bind方法內(nèi)參數(shù)為主。

實際應(yīng)用
    import React from 'react'

    export default class App extends React.component {
        state = {
            age: 24
        }
        
        constructor() {
            super()
            this.checkAdult = this.checkAdult.bind(this)
        }

        checkAdult() {
            console.log(this.state.age >= 18 ? '成年了' : '未成年')
        }

        render() {
            return (
                <button onClick={this.checkAdult}>檢測</button>
            )
        }
    }

react中,我們在可以在構(gòu)造函數(shù)內(nèi)實現(xiàn)this綁定(當(dāng)然我們也可以使用箭頭函數(shù)或者public class fields語法(stage 2)直接在class內(nèi)賦值)
react相關(guān)this指向相關(guān)問題

Math.max.apply(Math, [5, 2, 6, 9, 20, 12])

數(shù)組的求最大值(也可以使用es6的擴(kuò)展運(yùn)算符Math.max(...arr))

繼承

    function Animal(sound) {
        this.sound = sound
        this.say = function() {
            console.log(this.sound)
        }
    }

    function Dog() {
        Animal.apply(this, arguments)
    }

    const dog = new Dog('wang wang')

    dog.say()
    // wang wang

在構(gòu)造函數(shù)Dog內(nèi)使用call或者apply,此時Animal的所有屬性和方法都被在此聲明,實現(xiàn)繼承

偽數(shù)組轉(zhuǎn)換成數(shù)組

偽數(shù)組也稱類數(shù)組。像arguments 或者 獲取一組元素返回的集合都是偽數(shù)組。
(arguments,NodeList)

    const imgArr = Array.prototype.slice.call(document.querySelectorAll('img'))

    function Dog() {
        const ages = Array.prototype.slice.call(arguments)
    }

當(dāng)然也可以用ES6簡單寫法

const arg = Array.from(arguments);
const arg = [...arguments]
console.log(arg instanceof Array)
// true

Array.from() 能將類數(shù)組(arguments,NodeList),可迭代對象 (Set,Map),字符串(String)轉(zhuǎn)換成數(shù)組
Array.prototype.slice.call() 能將類數(shù)組(arguments,NodeList),字符串(String)轉(zhuǎn)換成數(shù)組

總結(jié)

  • call apply bind都有著改變this指向的作用,并且第一個參數(shù)都是目標(biāo)this對象,bind返回一個新的函數(shù)
  • 額外參數(shù)下,callbind的參數(shù)都以散列形式,apply以數(shù)組形式

在不破壞原對象的情況下,使用這幾個方法是最好的選擇。但隨著新版es的出現(xiàn),他們的大部分功能都已能被新的語法糖替代。不過對于開發(fā)者來說,但還是應(yīng)該要了解的,這些知識經(jīng)常出現(xiàn)在面試題中,況且只有了解原理才能更熟練的掌握新語法的用法,小到api,大到框架,腳踏實地,才能走得更高。

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

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

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