如何在 javascript 中创建自己的调用函数?

How can create own call function in javascript?

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

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 上运行。

这是他们的 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);
};

唯一无法填充的是 fn.call(null),因为无法将原语转换为复杂类型,只有本机代码可以做到这一点

添加您自己的调用函数,如“_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)
}

像以前一样称呼它。第一个参数应该是一个对象。不然写个代码把它转成object。

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

虽然每个浏览器都有自己的实现 Javascript 的源代码,但您可以在此处找到使用 ECMA 规范实现的本机 Javascript 功能的数量:

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

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

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

在上面的答案中我可以看到已经使用了传播运算符,但是如果我们真的想对调用进行 pollyfill 那么我们应该避免传播 es6.I 的运算符和最新概念正在分享没有 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));
  }

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

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