成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

手寫call、apply、bind及相關(guān)面試題解析

TwIStOy / 1366人閱讀

摘要:我是前端我的全名是我是一個(gè)前端指向接收多個(gè)參數(shù),第一個(gè)是返回值返回值是一個(gè)函數(shù)上下文的,不會(huì)立即執(zhí)行??吕锘嚓P(guān)講解請移步簡版的實(shí)現(xiàn)就算完成了歡迎吐槽點(diǎn)贊

它們有什么不同?怎么用?

call 接收多個(gè)參數(shù),第一個(gè)為函數(shù)上下文也就是this,后邊參數(shù)為函數(shù)本身的參數(shù)。

        let obj = {
            name: "一個(gè)"
        }

        function allName(firstName, lastName) {
            console.log(this)
            console.log(`我的全名是“${firstName}${this.name}${lastName}”`)
        }
        // 很明顯此時(shí)allName函數(shù)是沒有name屬性的
        allName("我是", "前端") //我的全名是“我是前端”  this指向window
        allName.call(obj, "我是", "前端") //我的全名是“我是一個(gè)前端” this指向obj

apply

apply接收兩個(gè)參數(shù),第一個(gè)參數(shù)為函數(shù)上下文this,第二個(gè)參數(shù)為函數(shù)參數(shù)只不過是通過一個(gè)數(shù)組的形式傳入的。

allName.apply(obj, ["我是", "前端"])//我的全名是“我是一個(gè)前端” this指向obj
bind

bind 接收多個(gè)參數(shù),第一個(gè)是bind返回值返回值是一個(gè)函數(shù)上下文的this,不會(huì)立即執(zhí)行。

        let obj = {
            name: "一個(gè)"
        }

        function allName(firstName, lastName, flag) {
            console.log(this)
            console.log(`我的全名是"${firstName}${this.name}${lastName}"我的座右銘是"${flag}"`)
        }
        allName.bind(obj) //不會(huì)執(zhí)行
        let fn = allName.bind(obj)
        fn("我是", "前端", "好好學(xué)習(xí)天天向上")

        // 也可以這樣用,參數(shù)可以分開傳。bind后的函數(shù)參數(shù)默認(rèn)排列在原函數(shù)參數(shù)后邊
        fn = allName.bind(obj, "你是")
        fn("前端", "好好學(xué)習(xí)天天向上")

接下來搓搓手實(shí)現(xiàn)call、apply和bind

實(shí)現(xiàn)call
      let Person = {
            name: "Tom",
            say() {
                console.log(this)
                console.log(`我叫${this.name}`)
            }
        }

        // 先看代碼執(zhí)行效果
        Person.say() //我叫Tom 
        Person1 = {
            name: "Tom1"
        }

        // 我們嘗試用原生方法call來實(shí)現(xiàn)this指向Person1
        Person.say.call(Person1) //我叫Tom1

通過第一次打印執(zhí)行和第二次打印執(zhí)行我發(fā)現(xiàn),如果Person1有say方法那么Person1直接執(zhí)行Person1.say() 結(jié)果就是我是Tom1,是的call就是這么實(shí)現(xiàn)的。
再看代碼

        Function.prototype.MyCall = function(context) {
            //context就是demo中的Person1
            // 必須此時(shí)調(diào)用MyCall的函數(shù)是say方法,那么我們只需要在context上擴(kuò)展一個(gè)say方法指向調(diào)用MyCall的say方法這樣this
            console.log(this)
            context.say = this //Mycall里邊的this就是我們虛擬的say方法
            context.say()
        }
        // 測試
        Person.say.MyCall(Person1)//我叫Tom1


perfect!爆棚的滿足感!不過拿腳趾頭想想也不會(huì)這么簡單,繼續(xù)完善
我們自己找茬
1、call支持多個(gè)參數(shù),有可能一個(gè)也不沒有
2、考慮多參數(shù)時(shí)要把參數(shù)傳給擴(kuò)展方法。
3、給上下文定義的函數(shù)要保持唯一不能是say
4、擴(kuò)展完我們需要吧自定義函數(shù)刪除
接下來針對(duì)找茬問題一一解決

        let Person = {
            name: "Tom",
            say() {
                console.log(this)
                console.log(`我叫${this.name}`)
            }
        }
        Person1 = {
            name: "Tom1"
        }
        //如果沒有參數(shù)
        Person.say.call()

沒有指定this,this指向window

我們也要這樣

        Function.prototype.MyCall = function(context) {
            // 如果沒有參數(shù)我們參考call的處理方式
            context = context || window
                //context就是demo中的Person1
                // 必須此時(shí)調(diào)用MyCall的函數(shù)是say方法,那么我們只需要在context上擴(kuò)展一個(gè)say方法指向調(diào)用MyCall的say方法這樣this
            context.say = this //Mycall里邊的this就是我們虛擬的say方法
            context.say()
        }

        Person.say.MyCall()


沒毛??!
繼續(xù)解決

// 找茬2:我們默認(rèn)定義context.say = this  fn如果已經(jīng)被占用 嘎嘎 sb了。 不怕 搞定它

        // say需要是一個(gè)唯一值 是不是突然想到es6的新類型 Symbol   fn = Symbol() 不過我們裝逼不嫌事大 都說自己實(shí)現(xiàn)了

        function mySymbol(obj) {
            // 不要問我為什么這么寫,我也不知道就感覺這樣nb
            let unique = (Math.random() + new Date().getTime()).toString(32).slice(0, 8)
                // 牛逼也要嚴(yán)謹(jǐn)
            if (obj.hasOwnProperty(unique)) {
                return mySymbol(obj) //遞歸調(diào)用
            } else {
                return unique
            }
        }
//接下來我們一并把多參數(shù)和執(zhí)行完刪除自定義方法刪除掉一塊搞定
        Function.prototype.myCall1 = function(context) {
            // 如果沒有傳或傳的值為空對(duì)象 context指向window
            context = context || window
            let fn = mySymbol(context)
            context.fn = this //給context添加一個(gè)方法 指向this
            // 處理參數(shù) 去除第一個(gè)參數(shù)this 其它傳入fn函數(shù)
            let arg = [...arguments].slice(1) //[...xxx]把類數(shù)組變成數(shù)組,arguments為啥不是數(shù)組自行搜索 slice返回一個(gè)新數(shù)組
            context.fn(...arg) //執(zhí)行fn
            delete context.fn //刪除方法
        }
        
        let Person = {
            name: "Tom",
            say(age) {
                console.log(this)
                console.log(`我叫${this.name}我今年${age}`)
            }
        }

        Person1 = {
            name: "Tom1"
        }

        Person.say.call(Person1,18)//我叫Tom1我今年18

測試結(jié)果相當(dāng)完美!

實(shí)現(xiàn)apply

接下來apply就簡單多了,只有多參數(shù)時(shí)第二個(gè)參數(shù)是數(shù)組,就不一步步細(xì)說了。

        Function.prototype.myApply = function(context) {
            // 如果沒有傳或傳的值為空對(duì)象 context指向window
            if (typeof context === "undefined" || context === null) {
                context = window
            }
            let fn = mySymbol(context)
            context.fn = this //給context添加一個(gè)方法 指向this
                // 處理參數(shù) 去除第一個(gè)參數(shù)this 其它傳入fn函數(shù)
            let arg = [...arguments].slice(1) //[...xxx]把類數(shù)組變成數(shù)組,arguments為啥不是數(shù)組自行搜索 slice返回一個(gè)新數(shù)組
            context.fn(arg) //執(zhí)行fn
            delete context.fn //刪除方法

        }
實(shí)現(xiàn)bind

這個(gè)和call、apply區(qū)別還是很大的,容我去抽根煙回來收拾它
還是老套路先分析bind都能干些什么,有什么特點(diǎn)

    1、函數(shù)調(diào)用,改變this
    2、返回一個(gè)綁定this的函數(shù)
    3、接收多個(gè)參數(shù)
    4、支持柯里化形式傳參 fn(1)(2)
    
       Function.prototype.bind = function(context) {
            //返回一個(gè)綁定this的函數(shù),我們需要在此保存this
            let self = this
                // 可以支持柯里化傳參,保存參數(shù)
            let arg = [...arguments].slice(1)
                // 返回一個(gè)函數(shù)
            return function() {
                //同樣因?yàn)橹С挚吕锘问絺鲄⑽覀冃枰俅潍@取存儲(chǔ)參數(shù)
                let newArg = [...arguments]
                console.log(newArg)
                    // 返回函數(shù)綁定this,傳入兩次保存的參數(shù)
                    //考慮返回函數(shù)有返回值做了return
                return self.apply(context, arg.concat(newArg))
            }
        }

        // 搞定測試
        let fn = Person.say.bind(Person1)
        fn()
        fn(18)

是的,完美,實(shí)現(xiàn)了綁定this,返回函數(shù),不立即執(zhí)行,可以柯里化形式傳參。柯里化相關(guān)講解請移步:https://segmentfault.com/a/11...

簡版的實(shí)現(xiàn)就算完成了

歡迎吐槽or點(diǎn)贊!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/101171.html

相關(guān)文章

  • 【周刊-1】三年大廠面試官-面試精選答案

    摘要:前言在阿里和騰訊工作了年,當(dāng)了年的前端面試官,把期間我和我的同事常問的面試題和答案匯總在我的中。項(xiàng)目地址是我是小蝌蚪,騰訊高級(jí)前端工程師,跟著我一起每周攻克幾個(gè)前端技術(shù)難點(diǎn)。 前言 在阿里和騰訊工作了6年,當(dāng)了3年的前端面試官,把期間我和我的同事常問的面試題和答案匯總在我 Github 的 Weekly-FE-Interview 中。希望對(duì)大家有所幫助。 如果你在bat面試的時(shí)候遇到了...

    ThinkSNS 評(píng)論0 收藏0
  • 【周刊-1】三年大廠面試官-面試精選答案

    摘要:前言在阿里和騰訊工作了年,當(dāng)了年的前端面試官,把期間我和我的同事常問的面試題和答案匯總在我的中。項(xiàng)目地址是我是小蝌蚪,騰訊高級(jí)前端工程師,跟著我一起每周攻克幾個(gè)前端技術(shù)難點(diǎn)。 前言 在阿里和騰訊工作了6年,當(dāng)了3年的前端面試官,把期間我和我的同事常問的面試題和答案匯總在我 Github 的 Weekly-FE-Interview 中。希望對(duì)大家有所幫助。 如果你在bat面試的時(shí)候遇到了...

    Bamboy 評(píng)論0 收藏0
  • 面試里的那些各種手寫

    摘要:最近準(zhǔn)備初級(jí)前端面試,發(fā)現(xiàn)有很多手寫實(shí)現(xiàn)什么的,例如什么手寫實(shí)現(xiàn),。后面以這道題為引線面試官可能會(huì)追問什么是執(zhí)行上下文的判斷,的區(qū)別手寫一個(gè)函數(shù)實(shí)現(xiàn)斐波那契數(shù)列首先拷一個(gè)阮神在他教程里的一個(gè)寫法。 最近準(zhǔn)備初級(jí)前端面試,發(fā)現(xiàn)有很多手寫實(shí)現(xiàn)什么的,例如什么手寫實(shí)現(xiàn)bind,promise。手寫ajax,手寫一些算法。翻閱了很多書籍和博客。 這里做一個(gè)總結(jié)改進(jìn),算是對(duì)我后面大概為期一個(gè)月找...

    wh469012917 評(píng)論0 收藏0
  • 22道JavaScript高頻手寫面試

    JavaScript筆試部分 點(diǎn)擊關(guān)注本公眾號(hào)獲取文檔最新更新,并可以領(lǐng)取配套于本指南的 《前端面試手冊》 以及最標(biāo)準(zhǔn)的簡歷模板. 實(shí)現(xiàn)防抖函數(shù)(debounce) 防抖函數(shù)原理:在事件被觸發(fā)n秒后再執(zhí)行回調(diào),如果在這n秒內(nèi)又被觸發(fā),則重新計(jì)時(shí)。 那么與節(jié)流函數(shù)的區(qū)別直接看這個(gè)動(dòng)畫實(shí)現(xiàn)即可。 showImg(https://segmentfault.com/img/remote/146000002...

    Alan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<