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

資訊專欄INFORMATION COLUMN

call、bind的模擬實(shí)現(xiàn)

mmy123456 / 795人閱讀

摘要:大致就是這樣所以可以模擬實(shí)現(xiàn)和。這些參數(shù)作為的第二個(gè)參數(shù)跟在后面,之后它們會(huì)被插入到目標(biāo)函數(shù)的參數(shù)列表的開始位置,傳遞給綁定函數(shù)的參數(shù)會(huì)跟在它們的后面。

一個(gè)前端知識(shí)點(diǎn)匯總

綜合了學(xué)習(xí)過程中的知識(shí)點(diǎn),比如this、閉包、BFC、ES6等,如果大佬們覺得還可以的話,求個(gè)star啦!

call和apply

每個(gè)函數(shù)都包含兩個(gè)非繼承而來的方法:apply()和call()

用途相同,都是在特定的作用域中調(diào)用函數(shù)

接收參數(shù)方面不同,apply接收兩個(gè)參數(shù),一個(gè)是函數(shù)運(yùn)行時(shí)的作用域(this),另一個(gè)是參數(shù)數(shù)組;call方法第一個(gè)參數(shù)與apply方法相同,但傳遞給函數(shù)的參數(shù)必須列舉出來。

call()方法調(diào)用一個(gè)函數(shù),其具有一個(gè)指定的this值和分別提供的參數(shù):

fun.call(thisArg, arg1, arg2, ...)

apply()方法調(diào)用一個(gè)函數(shù),其具有一個(gè)指定的this值,以及作為一個(gè)數(shù)組(或類似數(shù)組的對(duì)象)提供的參數(shù):

fun.apply(thisArg, [argsArray])

舉個(gè)栗子???:

var one = {
    name: "one",
    sayName: function(age) {
        console.log(`Hello, I"m ${this.name}, and I"m ${age} years old`)
    }
}
var day = {
    name: "day"
}
one.sayName.call(day, 20) // Hello, I"m day, and I"m 20 years old
one.sayName.apply(day, [20]) // Hello, I"m day, and I"m 20 years old

fn.call(o)的原理就是先通過o.m = fn將fn作為o的某個(gè)臨時(shí)屬性m存儲(chǔ),然后執(zhí)行m,執(zhí)行完畢后將m屬性刪除。

大致就是這樣:

day.fn = one.sayName
day.fn()
delete day.fn

所以可以模擬實(shí)現(xiàn)apply和call。

首先來看apply的模擬:

第一版
Function.prototype.applyOne = function() {
    var context = arguments[0]
    var args = arguments[1]
    context.fn = this
    eval(context.fn(args.join(","))) // args.join(",")返回的是string,所以需要進(jìn)行一下特殊處理)
    delete context.fn
}

one.sayName.applyOne(day, [20]) // Hello, I"m day, and I"m 20 years old
第二版

要注意到的是,若this傳入的是null,或者不傳入,則會(huì)默認(rèn)是全局環(huán)境,并且apply是有返回值的。

Function.prototype.applyTwo = function() {
    var context = arguments[0] || window
    var args = arguments[1]
    context.fn = this

    if (args == void 0) {
        return context.fn()
    } 
    var result = eval(context.fn(args.join(","))) // args.join(",")返回的是string,所以需要進(jìn)行一下特殊處理
    delete context.fn
    return result
}

var name = "oneday"

var one = {
    name: "one",
    sayName: function(age) {
        console.log(`Hello, I"m ${this.name}, and I"m ${age} years old`)
    }
}
var day = {
    name: "day"
}
one.sayName.applyTwo(null, [20]) // Hello, I"m oneday, and I"m 20 years old

emmmm...有一個(gè)問題就是萬一context里面本來就有fn屬性怎么辦呢...對(duì)于es6而言,可以將fn設(shè)置為一個(gè)獨(dú)特的Symbol值,如下:

var fn1 = Symbol("aaa")
var fn2 = Symbol("aaa")
fn1 == fn2 // false

但是畢竟symbol是es6的特性啊,所以在es5中可以使用產(chǎn)生隨機(jī)數(shù)的方法,例如:

var fn1 = "o" + Math.random()
var fn2 = "o" + Math.random()

接下來就是apply:

Function.prototype.callOne = function() {
    var context = [].shift.applyTwo(arguments)
    var args = [].slice.applyTwo(arguments) // 將剩下的參數(shù)作為數(shù)組傳入啊
    return this.applyTwo(context, args)
}

emmmm...第一個(gè)參數(shù)就是arguments的第一個(gè)(一般是this,或者沒有),后面的參數(shù)就作為數(shù)組形式傳入。

bind方法

bind方法創(chuàng)建一個(gè)新的函數(shù),當(dāng)被調(diào)用時(shí),this值是傳遞給bind的第一個(gè)參數(shù),它的參數(shù)是bind其他的參數(shù)和其原本的參數(shù),返回的是由指定的this值和初始化參數(shù)改造的原函數(shù)拷貝。

fun.bind(thisArg[, arg1[, arg2[, ...]]])

實(shí)例:

var name = "2333"
function Person(name) {
    this.name = name
    this.sayName = function() {
        setTimeout(function() {
            console.log(`Hello, I"m ${this.name}`)
        }, 1000)
    }
}

var oneday = new Person("1111")
oneday.sayName() // Hello, I"m 2333

但是下面這樣就是1111~

this.sayName = function() {
    setTimeout(function() {
        console.log(`Hello, I"m ${this.name}`)
    }.bind(this), 1000)
}

var oneday = new Person("1111")
oneday.sayName() // Hello, I"m 1111

而且還有偏函數(shù)(Partial Functions),在mdn中是這么說的:

bind()的另一個(gè)最簡(jiǎn)單的用法是使一個(gè)函數(shù)擁有預(yù)設(shè)的初始參數(shù)。這些參數(shù)作為bind()的第二個(gè)參數(shù)跟在this后面,之后它們會(huì)被插入到目標(biāo)函數(shù)的參數(shù)列表的開始位置,傳遞給綁定函數(shù)的參數(shù)會(huì)跟在它們的后面。

emmmm...對(duì)呀?jīng)]看懂,于是就看例子啊...

function list() {
    return Array.prototype.slice.call(arguments)
}

var list1 = list(1, 2, 3) // [1, 2, 3]

// 所以listFun是擁有預(yù)設(shè)參數(shù)(5, 6)的,作為預(yù)設(shè)參數(shù)跟在第一個(gè)參數(shù)this后面
var listFun = list.bind(undefined, 5, 6)

// 后面?zhèn)魅氲膮?shù)會(huì)跟在預(yù)設(shè)參數(shù)的后面
var list2 = listFun(7) // [5, 6, 7]
var list3 = listFun(8, 9) // [5, 6, 8, 9]

bind的模擬實(shí)現(xiàn):

第一版
Function.prototype.bindOne = function() {
    var me = this // 緩存this
    var argArray = Array.prototype.slice.call(arguments, 1)
    return function() {
        return me.apply(arguments[0], argArray)
    }
}

但是上述的沒有實(shí)現(xiàn)繼續(xù)傳參可以添加到原參數(shù)后的功能...所以有了第二版

第二版
Function.prototype.bindTwo = function() {
    var context = arguments[0]
    var me = this
    var argArray = Array.prototype.slice.call(arguments, 1)
    return function() {
        var innerArgs = Array.prototype.slice.call(arguments)
        var finalArgs = argArray.concat(innerArgs)
        return me.apply(context, finalArgs)
    }
}

bind返回的函數(shù)如果作為構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)搭配new關(guān)鍵字出現(xiàn)的話,bind綁定的this需要被忽略,但是參數(shù)還要繼續(xù)傳入。意思就是bind的綁定比new的優(yōu)先級(jí)要低。而且要在函數(shù)體內(nèi)判斷調(diào)用bind方法的一定要是一個(gè)函數(shù)。

復(fù)習(xí)一下new的作用:

創(chuàng)建一個(gè)新對(duì)象

新對(duì)象繼承了該函數(shù)的原型(因此this就指向了這個(gè)新對(duì)象)

為這個(gè)新對(duì)象添加屬性和方法并返回這個(gè)新對(duì)象

var obj = {}
obj.__proto__ = Base.prototype
Base.call(obj)
第三版
Function.prototype.bindThree = function() {
    if (typeof this !== "function") {
        throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable")
    }

    // context指要把this綁定到的目標(biāo)函數(shù)
    var context = arguments[0]

    // 這里的this指向調(diào)用bind的函數(shù)
    var me = this
    var argArray = Array.prototype.slice.call(arguments, 1)

    var F = function() {}
    F.prototype = this.prototype
    var bound = function() {
        var innerArgs = Array.prototype.slice.call(arguments)
        var finalArgs = argArray.concat(innerArgs)

        // 如果調(diào)用bind的函數(shù)是F的實(shí)例,那么this就還是指向調(diào)用bind的函數(shù),如果不是F的實(shí)例,那么this就進(jìn)行改變
        return me.apply(this instanceof F ? this : context, finalArgs)
    }
    bound.prototype = new F()
    return bound
}
參考:

不用call和apply方法模擬實(shí)現(xiàn)ES5的bind方法

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

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

相關(guān)文章

  • JavaScript深入之bind模擬實(shí)現(xiàn)

    摘要:也就是說當(dāng)返回的函數(shù)作為構(gòu)造函數(shù)的時(shí)候,時(shí)指定的值會(huì)失效,但傳入的參數(shù)依然生效。構(gòu)造函數(shù)效果的優(yōu)化實(shí)現(xiàn)但是在這個(gè)寫法中,我們直接將,我們直接修改的時(shí)候,也會(huì)直接修改函數(shù)的。 JavaScript深入系列第十一篇,通過bind函數(shù)的模擬實(shí)現(xiàn),帶大家真正了解bind的特性 bind 一句話介紹 bind: bind() 方法會(huì)創(chuàng)建一個(gè)新函數(shù)。當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),bind() 的第一個(gè)參數(shù)...

    FingerLiu 評(píng)論0 收藏0
  • JavaScript進(jìn)階之模擬call,apply和bind

    摘要:模擬和模擬一樣,現(xiàn)摘抄下面的代碼添加一個(gè)返回值對(duì)象然后我們定義一個(gè)函數(shù),如果執(zhí)行下面的代碼能夠返回和函數(shù)一樣的值,就達(dá)到我們的目的。 原文:https://zhehuaxuan.github.io/... 作者:zhehuaxuan 目的 本文主要用于理解和掌握call,apply和bind的使用和原理,本文適用于對(duì)它們的用法不是很熟悉,或者想搞清楚它們?cè)淼耐? 好,那我們開始...

    CoderBear 評(píng)論0 收藏0
  • 【進(jìn)階3-4期】深度解析bind原理、使用場(chǎng)景及模擬實(shí)現(xiàn)

    摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對(duì)象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器,提供的值被忽略,同時(shí)調(diào)用時(shí)的參數(shù)被提供給模擬函數(shù)。 bind() bind() 方法會(huì)創(chuàng)建一個(gè)新函數(shù),當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),它的 this 值是傳遞給 bind() 的第一個(gè)參數(shù),傳入bind方法的第二個(gè)以及以后的參數(shù)加上綁定函數(shù)運(yùn)行時(shí)本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù)。bind返回的綁定函數(shù)也能使用 n...

    guyan0319 評(píng)論0 收藏0
  • 面試官問:能否模擬實(shí)現(xiàn)JSbind方法

    摘要:點(diǎn)擊那么面試官可能會(huì)問是否想過到底做了什么,怎么模擬實(shí)現(xiàn)呢。另外前不久寫過一篇文章面試官問能否模擬實(shí)現(xiàn)的操作符。所以相當(dāng)于調(diào)用時(shí),的返回值函數(shù)內(nèi)部要模擬實(shí)現(xiàn)實(shí)現(xiàn)的操作。文章中的例子和測(cè)試代碼放在中模擬實(shí)現(xiàn)。 前言 用過React的同學(xué)都知道,經(jīng)常會(huì)使用bind來綁定this。 import React, { Component } from react; class TodoItem ...

    Julylovin 評(píng)論0 收藏0
  • JavaScript專題之模擬實(shí)現(xiàn)bind

    摘要:但是三作為構(gòu)造函數(shù)時(shí)函數(shù)其實(shí)還有一個(gè)非常重要的特點(diǎn)返回的函數(shù)如果作為構(gòu)造函數(shù),搭配關(guān)鍵字出現(xiàn)的話,我們的綁定就需要被忽略。其次,當(dāng)返回的函數(shù)作為構(gòu)造函數(shù)時(shí),之前綁定的會(huì)失效。 本文共 1100 字,讀完只需 4 分鐘 概述 前一篇文章我們嘗試模擬實(shí)現(xiàn)了 call 和 apply 方法,其實(shí) bind 函數(shù)也可以用來改變 this 的指向。bind 和 call和 apply 兩者的區(qū)別...

    劉明 評(píng)論0 收藏0

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

0條評(píng)論

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