call、apply、bind學不會,來砍我!!!!——輕生前端

NO IMAGE

今天我們來說一下call、apply、bind這三兄弟的功能和區別順便自己封裝一下

call

介紹一下大哥call的功能

~~不管是call、apply還是bind作用都是為了改變函數中this的指向 ,所以他們的作用其實是大同小異滴! 先說call 舉個例子吧

function fn() {
        console.log(arguments)
        console.log(this)
    }

    var obj = {
        f: fn
    }

就說他吧你要是運行個fn.call(obj, 4, 4, 4)這個 按理說this應該指向’點’前邊的那位,但是呢咱們用了call那可就不一樣了,this就會指向call後邊括號裡第一個參數,當然首先咱們得保證那個函數不能是箭頭函數,箭頭函數嘛 不管咋樣this都指向他的上級,由此還得出一個結論 this的指向的權重!!! —箭頭函數 > call(apply,bind)這三兄弟 >”點” 然後括號中除了第一個參數之外剩下的都是 傳進去的參數
=====總之括號裡:

”第一個參數用函數執行時this的指向 後邊的參數都是傳給前邊函數的實參“

fn.call(obj, 4, 4, 4)他的結果就是4,4,4和obj了!

封裝一個咱們自己的call

~~對了奧call apply bind 這三兄弟 都是存在Function的原型裡邊的,我想在座的各位應該都知道吧!
既然他存在在Function的原型裡邊 我們不如 ? 嘿嘿嘿自己封裝一個? 說封就封!淦!

封裝之前加個小插曲es6中的…是剩餘運算符

let a = ['apple','banana','orange'];

console.log(...a); //apple, banana, orange

就這麼用的!!

開始封裝!!

    Function.prototype.myCall = function (context, ...ary) {
        var key = Symbol()
        context[key] = this
        context[key](...ary)
        delete context[key]
    }
    fn.myCall(obj, 6, 6, 6)

就這點代碼就ok了 context是他的形參也就是我們需要讓this指向的地方 …ary是解構了除了第一項之後的實參

//怎麼保證一個函數執行上下文是context
context.qqq() qqq執行時裡邊的 this就是context 但是呢這個qqq很有可能會和實參裡邊的屬性重複所以我們用了Symbol這個東西他就是一個唯一的東西 就不會重複啦為啥還要把他刪了呢
delete context[key]因為這樣我們會在實參obj中加一個新的屬性 所以為了不改變他就再刪掉他

雖然封裝一個功能和call相同的函數像是在白白費力,明明用call就可以解決我們還封裝,沒事找個樂子嘛!也鍛鍊鍛鍊腦袋!

apply

然後咱們開始介紹老二

~~為啥說他三是三兄弟其實他們三真的很像 apply似於call 但是第二個參數是一個集合 (數組或者類數組),

fn.apply(obj, [6, 6, 6])

和call一樣一樣的 就是後邊參數必須得是數組或者類數組,也就是說呀他傳進去之後會自動把這個數組或者類數組散開,和call好像啊!所以奧老二就介紹到這裡了 哈哈哈哈!

bind

介紹一下老么吧

~~這三兄弟是不是三胞胎?bind的用法和call 一模一樣 只是不是讓函數立即執行的而是返回一個新函數,新函數執行時 ,裡邊的this 會改變成 指定的對象

看個小例子吧:

var fn2 = fn.bind(obj, 6, 6, 6)
    fn2()

讓fn執行並且把fn中的this 改成了obj,還把6,6,6傳給了fn 就是呀新函數執行後他的this才會變其他和call是一樣滴

咱們再封裝個自己的bind?

淦!來 !fn咱們還用上邊的奧 就不寫了

    Function.prototype.myBind = function (context, ...arg) {
        var _this = this 
        return function (...ary) {
             _this.call(context, ...arg)

        }
    }

注意奧var _this=this就是存儲的就是fn函數 其實呀就是讓call的返回值再加一步函數這樣就可以讓他運行之後他再讓this指向咱們第一項的參數了

還有一個簡單的方法:

Function.prototype.myBind=function(context,...arg){
            return(...ary)=>{
                this.call(context,...arg,...ary)
            }
        }

其實和上邊意思是一樣的 就是換成了箭頭函數this就自己找他去了

結尾

學會了吧?沒學會的話我要跑路的。不過apply 已經再找我麻煩了,拿著四十米的大刀追問我為啥不給他封裝一個函數!!!

都看到這了還不三連?

相關文章

如何學習一門語言

堆內存,棧內存的的銷燬

任意數求和解析

用正則驗證身份證,手機號的合法性(寬鬆)