Interview questions: achieve call, apply, bind

Interview questions: achieve call, apply, bind

Realization bind

module.exports = function(context, ...args) {
  let withArgs = args.length != 0; //是否传参
  let isConstructor;
  try {
    new this(...args); //是构造函数则不会因为new执行报错
    isConstructor = true;
  } catch (error) {
    //不是构造函数
    isConstructor = false;
  }

  if (isConstructor) {
    if (typeof context === "object" && context !== null)
      //context是有效对象
      return withArgs
        ? () => Object.assign(context, new this(...args)) //若带参,返回的函数不需要处理接收参数
        : (...args) => Object.assign(context, new this(...args)); //若不带参,返回的函数需要处理接收参数
    
    else throw new Error("Illegal context"); //context是无效对象
  } else {
    return ()=>this(...args);
  }
};

To achieve call

After the realization of the bind, to bind only need to call the conversion process on it

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

Realize apply

After the realization of the call, only to deal with the next parameter, the conversion process will be able to call

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

use

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

After the mount on the prototype, you can normally use

test

1, bind test

require(".") //导入模块

const obj = {
    q: "1"
}

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

//一、使用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")
}


//二、使用bind的函数是构造函数,context是无效对象
//测试bind带参,执行函数不带参的情况 => 捕获报错输出ok
try {
    console.log(Parent.newBind(null,3,2)())
} catch (error) {
    console.log("ok")
}

//测试bind带参,执行函数带参的情况 => 捕获报错输出ok
try {
    console.log(Parent.newBind(null,3,2)(3,4))
} catch (error) {
    console.log("ok")
}

//测试bind不带参的情况,执行函数不带参的情况 => 捕获报错输出ok
try {
    console.log(Parent.newBind(null)())
} catch (error) {
    console.log("ok")
}

//测试bind带参,执行函数带参的情况 => 捕获报错输出ok
try {
    console.log(Parent.newBind(null)(3,4))
} catch (error) {
    console.log("ok")
}



//三、使用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("测试完成")

2, call the test

require(".") //导入模块

const obj = {
    q: "1"
}

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

//一、使用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")
}

//二、使用call的函数是构造函数,context是无效对象
//测试call带参 => 捕获报错输出ok
try {
    console.log(Parent.newCall(null,3,2))
} catch (error) {
    console.log("ok")
}

//测试call不带参的情况 => 捕获报错输出ok
try {
    console.log(Parent.newCall(null))
} catch (error) {
    console.log("ok")
}

//三、使用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("测试完成")

3, apply the test

require(".") //导入模块

const obj = {
    q: "1"
}

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

//一、使用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")
}

//二、使用apply的函数是构造函数,context是无效对象
//测试apply带参 => 捕获报错输出ok
try {
    console.log(Parent.newApply(null,[3,2]))
} catch (error) {
    console.log("ok")
}

//测试apply不带参的情况 => 捕获报错输出ok
try {
    console.log(Parent.newApply(null))
} catch (error) {
    console.log("ok")
}

//三、使用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("测试完成")

After testing, to achieve call, apply, bind the basic function is ok

github address

Source

Guess you like

Origin www.cnblogs.com/failte/p/11032703.html