【问题标题】:How can create own call function in javascript?如何在javascript中创建自己的调用函数?
【发布时间】:2018-07-24 16:51:58
【问题描述】:

据我所知,在 javascript 中有三个概念;调用、应用和绑定 我想创建具有类似行为的这些函数。

【问题讨论】:

  • 你想达到什么目的?请准确解释您要做什么。您想与您列出的那些方法有什么不同?目前尚不清楚您要做什么。
  • 我想知道这些的内部行为,因为有人在 paytm 面试中问我
  • @JonasW。但不是call() 他们有一个用于bind() 的polyfill,但这取决于apply()
  • @zero298 这是一个测试你的JS技能的著名面试题
  • @SuryaprakashPatel 查看我的回复

标签: javascript function call


【解决方案1】:

这是他们的 polyfill(虽然不准确,只是我想到的):

Function.prototype.call = function(context, ...args) {
  const fn = Symbol();
  try {
    context[fn] = this; 
    return context[fn](...args);
   } catch(e) {
      // Turn primitive types into complex ones 1 -> Number, thanks to Mark Meyer for this.
     context = new context.constructor(context);
     context[fn] = this;
  }
  return context[fn](...args);
};

Function.prototype.apply = function(context, args) {
  return this.call(context, ...args);
};

Function.prototype.bind = function(context, ...args) {
  return (...args2) => this.call(context, ...args, ...args2);
};

唯一不能 polyfill 的就是 fn.call(null),因为这个原语不能变成复杂类型,只有原生代码才能做到这一点

【讨论】:

  • 请解释一下 Symbol()。
  • @JonasW。有趣...我删除了,因为我虽然混淆了一些东西,但也许不是。
  • 很高兴我找到了这个。只有一句话:我必须在 context[fn](...args) 前面添加一个 return 才能使调用替换工作。
  • 你能解释一下context[fn] = this; return context[fn](...args);这几行吗?
【解决方案2】:

添加你自己的调用函数,比如“_call”

Function.prototype._call = function(newcontext, ...arg){

var demoFn = new Function('tempfuncton', 'tempthis','arg' , '{ tempthis["f"]=tempfuncton; return tempthis.f(arg);}');
demoFn(this,newcontext,arg);
}

编写一个演示函数

function anyfunction(args){
console.log(this,args)
}

像以前一样调用它。第一个参数应该是一个对象。否则编写代码将其转换为对象。

anyfunction._call({'mm':'my provided this object'},"arg1","arg2")

【讨论】:

  • 在此处创建自己的函数调用与您之前的答案有何不同?
  • 还有,为什么你觉得有必要为此提供赏金?有大量关于在线调用/绑定/申请的资源。
【解决方案3】:
function B(a,b,c){
   console.log(a,b,c)
}

Function.prototype.OwnCallFunction = function(){  
    if( this.length == arguments.length)
        this(...arguments)
    else
        console.error('Signature does not match')
 } 
B.OwnCallFunction(323,34,34)

我按照这种方法创建了自己的调用函数。在 Function Constructor 的帮助下,我向其中添加了一个函数,它可以在 firefox 上运行。

【讨论】:

  • 不应该callthis 作为第一个参数吗?
  • @Mark 请给我建议更多更好的方法。
  • 我不知道如何在不使用其他功能的情况下做到这一点,但如果它像call() 一样工作,它需要能够绑定@ 987654325@ 传递给第一个参数的对象。
  • 这取决于B的定义,它需要多少个参数。
【解决方案4】:

在上面的答案中,我可以看到已经使用了传播运算符,但是如果我们真的想对 call 进行 pollyfill,那么我们应该避免传播 运营商和 es6 的最新概念。我正在分享没有 es6 的解决方案。

调用函数:-

Function.prototype.myCall = function(obj) {
   obj = obj || global;
   var id = "00" + Math.random();
  while (obj.hasOwnProperty(id)) {
    id = "00" + Math.random();
  }
  obj[id] = this;
  let arg=[];
  for(let i=1;i<arguments.length;i++){
       arg.push("arguments[" + i + "]");
  }
 result= eval("obj[id]("+arg+")");
  delete obj[id];
  return result;
}

应用函数:-

Function.prototype.myApply = function(obj, argArr) {
 obj = obj || global;
 var id = "00" + Math.random();
 while (obj.hasOwnProperty(id)) {
  id = "00" + Math.random();
 }
 obj[id] = this;
 let arg=[];
 let result
 if(!argArr){
  result= obj[id].fn();
 }
 else{
  for(let i=0;i<argArr.length;i++){
      arg.push("argArr[" + i + "]");
     }
  result= eval("obj[id]("+arg+")");
  delete obj[id];
}
return result;

}

绑定函数:-

Function.prototype.myBind2= function(){
  let obj1= this;
  const obj= Array.prototype.slice.call(arguments,0,1);
   const arg= Array.prototype.slice.call(arguments,1);
  return function(){
    const arg2= Array.prototype.slice.call(arguments);
   obj1.apply(obj[0],Array.prototype.concat(arg, arg2));
}

另一种解决方案绑定:我们可以传递函数的对象参数

Function.prototype.myBind2 = function(obj) {
  let fn = this;
  const arg = Array.prototype.slice.call(arguments, 1);
  return function() {
    const arg2 = Array.prototype.slice.call(arguments);
    fn.apply(obj, Array.prototype.concat(arg, arg2));
  }

【讨论】:

    【解决方案5】:

    虽然每个浏览器都有自己的实现 Javascript 的源代码,但您可以在此处找到有多少原生 Javascript 函数是使用 ECMA 规范实现的:

    http://www.ecma-international.org/ecma-262/10.0/index.html#sec-properties-of-the-function-prototype-object

    apply 的规格见:19.2.3.1

    bind 的规格见:19.2.3.2

    call 的规格见:19.2.3.3

    如果您对 Node 如何实现 apply 感兴趣,您可以在 Github 上挖掘他们的源代码:https://github.com/nodejs/node

    【讨论】:

      【解决方案6】:

      这是我甜蜜而简单的解决方案。我们在原型链中添加 ObjRef 以避免与其他属性发生任何名称冲突

          Function.prototype.call2 = function (objRef, ...args) {
            otherObj = Object.create(objRef)
            otherObj[this.name] = this;
            otherObj[this.name](...args);
          }
      

      【讨论】:

        【解决方案7】:

        我认为在这里使用Object.create 没有意义,因为当您在函数内控制台this 时,您将看不到所需的对象。 这是我的尝试(虽然不准确),但会奏效。

        Function.prototype.myCall = function (thisContext, ...param) {
            let name = this.name;
            thisContext[name] = this;
            thisContext[name](...param);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-27
          • 2020-04-06
          • 2015-06-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多