面試題:實現call、apply、bind

面試題:實現call、apply、bind

實現bind

module.exports = function(Tcontext, ...args) {
  let globalThis = typeof window === "undefined" ? global : window;
  let context = typeof Tcontext === "undefined" ? globalThis : Tcontext;
  let withArgs = args.length != 0; //是否傳參
  if (!!this.prototype && typeof context === "object" && context !== null) {
    //context是有效對象
    return withArgs
      ? () => Object.assign(context, new this(...args)) //若帶參,返回的函數不須要處理接收參數
      : (...args) => Object.assign(context, new this(...args)); //若不帶參,返回的函數須要處理接收參數
  } else {
    return withArgs
    ? ()=>this(...args)
    : (...args)=>this(...args)
  }
};

實現call

在實現了bind後,只須要將call轉換給bind處理就能夠了git

module.exports = function(context, ...args){
    return this.newBind(context, ...args)()
}

實現apply

實現了call後,只須要處理下參數,轉換給call處理就能夠了github

module.exports = function(context, args){
    return args instanceof Array?this.newCall(context, ...args):this.newCall(context)
}

使用

const newBind = require("./bind")
const newCall = require("./call")
const newApply = require("./apply")

Function.prototype.newBind = newBind //將bind掛載到Function原型,使得任何實例能夠像使用bind通常使用newBind
Function.prototype.newCall = newCall //將call掛載到Function原型,使得任何實例能夠像使用call通常使用newCall
Function.prototype.newApply = newApply //將apply掛載到Function原型,使得任何實例能夠像使用apply通常使用newApply

在掛載到原型上後,就能夠正常使用了面試

測試

一、bind的測試數組

require(".") //導入模塊

const obj = {
    q: "1"
}

const Parent = function(a, b){
    this.a = a;
    this.b = b
}

//1、使用bind的函數是構造函數,context是有效對象
//測試bind帶參,執行函數不帶參的狀況
try {
    console.log(Parent.newBind(obj,3,2)())
} catch (error) {
    if(error.toString()=="Illegal context") console.log("err")
    else console.log("Failed")
}

//測試bind帶參,執行函數帶參的狀況 => 執行函數的參數不生效
try {
    console.log(Parent.newBind(obj,3,2)(3,4))
} catch (error) {
    if(error.toString()=="Illegal context") console.log("err")
    else console.log("Failed")
}

//測試bind不帶參的狀況,執行函數不帶參的狀況 => 執行函數的參數應爲undefined
try {
    console.log(Parent.newBind(obj)())
} catch (error) {
    if(error.toString()=="Illegal context") console.log("err")
    else console.log("Failed")
}

//測試bind帶參,執行函數帶參的狀況 => 執行函數的帶參應生效
try {
    console.log(Parent.newBind(obj)(3,4))
} catch (error) {
    if(error.toString()=="Illegal context") console.log("err")
    else console.log("Failed")
}


//2、使用bind的函數是構造函數,context是無效對象
//測試bind帶參,執行函數不帶參的狀況
console.log(Parent.newBind(null,3,2)())

//測試bind帶參,執行函數帶參的狀況
console.log(Parent.newBind(null,3,2)(3,4))

//測試bind不帶參的狀況,執行函數不帶參的狀況
console.log(Parent.newBind(null)())

//測試bind帶參,執行函數帶參的狀況
console.log(Parent.newBind(null)(3,4))

//3、使用bind的函數不是構造函數
console.log(Math.pow.newBind(obj, 3, 2)())
console.log(Math.pow.newBind(null, 3, 2)())
console.log(Math.pow.newBind(1, 3, 2)())
console.log(Math.pow.newBind(null)(2,3))


console.log("測試完成")

二、call的測試app

require(".") //導入模塊

const obj = {
    q: "1"
}

const Parent = function(a, b){
    this.a = a;
    this.b = b
}

//1、使用call的函數是構造函數,context是有效對象
//測試call帶參
try {
    console.log(Parent.newCall(obj,3,2))
} catch (error) {
    if(error.toString()=="Illegal context") console.log("err")
    else console.log("Failed")
}


//測試call不帶參的狀況 => 執行函數的參數應爲undefined
try {
    console.log(Parent.newCall(obj))
} catch (error) {
    if(error.toString()=="Illegal context") console.log("err")
    else console.log("Failed")
}

//2、使用call的函數是構造函數,context是無效對象
//測試call帶參
console.log(Parent.newCall(null,3,2))

//測試call不帶參的狀況
console.log(Parent.newCall(null))

//3、使用call的函數不是構造函數
console.log(Math.pow.newCall(obj, 3, 2))
console.log(Math.pow.newCall(null, 3, 2))
console.log(Math.pow.newCall(1, 3, 2))


console.log("測試完成")

三、apply的測試函數

require(".") //導入模塊

const obj = {
    q: "1"
}

const Parent = function(a, b){
    this.a = a;
    this.b = b
}

//1、使用apply的函數是構造函數,context是有效對象
//測試apply帶參
try {
    console.log(Parent.newApply(obj,[3,2]))
} catch (error) {
    if(error.toString()=="Illegal context") console.log("err")
    else console.log("Failed")
}


//測試apply不帶參的狀況 => 執行函數的參數應爲undefined
try {
    console.log(Parent.newApply(obj))
} catch (error) {
    console.log(error);
    if(error.toString()=="Illegal context") console.log("err")
    else console.log("Failed")
}

//2、使用apply的函數是構造函數,context是無效對象
//測試apply帶參
console.log(Parent.newApply(null,[3,2]))

//測試apply不帶參的狀況
console.log(Parent.newApply(null))

//3、使用apply的函數不是構造函數
console.log(Math.pow.newApply(obj, [3, 2]))
console.log(Math.pow.newApply(null, [3, 2]))
console.log(Math.pow.newApply(1, [3, 2]))
console.log(Math.pow.newApply(1, 3, 2)) //第二個參數不爲數組,結果應異常


console.log("測試完成")

通過測試,實現call、apply、bind基本功能是ok的測試

github地址

源碼ui

相關文章
相關標籤/搜索