Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

call apply bind #30

Open
Sunny-117 opened this issue Nov 3, 2022 · 13 comments
Open

call apply bind #30

Sunny-117 opened this issue Nov 3, 2022 · 13 comments

Comments

@Sunny-117
Copy link
Owner

Function.prototype.call2 = function(context, ...args) {
  context = (context === undefined || context === null) ? window : context
  context.__fn = this
  let result = context.__fn(...args)
  delete context.__fn
  return result
}
Function.prototype.apply2 = function(context, args) {
  context = (context === undefined || context === null) ? window : context
  context.__fn = this
  let result = context.__fn(...args)
  delete context.__fn
  return result
}
Function.prototype.bind2 = function(context, ...args1) {
  context = (context === undefined || context === null) ? window : context
  let _this = this
  return function(...args2) {
    context.__fn = _this
    let result = context.__fn(...[...args1, ...args2])
    delete context.__fn
    return result
  }
}
@veneno-o
Copy link
Contributor

Function.prototype._call = function (obj, ...args) {
	!obj && (obj = globalThis);
	// this代表要执行的函数
	obj._fn = this;
	const res = obj._fn(...args);
	delete obj._fn;
	return res;
};

Function.prototype._apply = function (obj, args) {
	// 第二个参数必须为数组或类数组对象, 否则初始化为空对象
	const arr = [];
	for (let i = 0; i < args?.length; ++i) {
		arr.push(args[i]);
	}
	return this._call(obj, ...arr);
};

Function.prototype._bind = function (obj, ...args1) {
	!obj && (obj = globalThis);
	return (...args2) => {
        obj._fn = this;
		const res = obj._fn(...[...args1, ...args2]);
		delete obj._fn;
		return res;
	};
};

@bearki99
Copy link

bearki99 commented Feb 2, 2023

Function.prototype._myCall = function(thisArg, ...args)  {
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  let fn = Symbol();
  thisArg[fn] = this;
  const res = thisArg[fn](...args);
  delete thisArg[fn];
  return res;
};
Function.prototype._myapply = function(thisArg, args = [])  {
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  let fn = Symbol();
  thisArg[fn] = this;
  const res = thisArg[fn](...args);
  delete thisArg[fn];
  return res;
};
Function.prototype._mybind = function(thisArg, ...args)  {
  let fn = this;
  return (...args) => {
    return fn._myCall(thisArg, ...args);
  };
};
//最好使用symbol进行处理一下,以及对于apply传递的数组考虑一下为空的情况

@Tylermeek
Copy link

Tylermeek commented Feb 13, 2023

// 该代码为上面同学提交的,虽然考虑到了边界条件,更加严谨,但是是有问题的,会使始终指向全局对象window
// 问题就出在这个箭头函数,因为箭头函数的特性,会无法获得到正确的this,即调用call的函数
//  !!!处理方式:更改为function(){}即可
Function.prototype._myCall = (thisArg, ...args) => {
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  let fn = Symbol();
  thisArg[fn] = this;
  const res = thisArg[fn](...args);
  delete thisArg[fn];
  return res;
};
// 同理
Function.prototype._myapply = (thisArg, args = []) => {
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  let fn = Symbol();
  thisArg[fn] = this;
  const res = thisArg[fn](...args);
  delete thisArg[fn];
  return res;
};
// 同理
Function.prototype._mybind = (thisArg, ...args) => {
  let fn = this;
  return (...args) => {
    return fn._myCall(thisArg, ...args);
  };
};
//最好使用symbol进行处理一下,以及对于apply传递的数组考虑一下为空的情况

@bearki99
Copy link

// 该代码为上面同学提交的,虽然考虑到了边界条件,更加严谨,但是是有问题的,会使始终指向全局对象window
// 问题就出在这个箭头函数,因为箭头函数的特性,会无法获得到正确的this,即调用call的函数
//  !!!处理方式:更改为function(){}即可
Function.prototype._myCall = (thisArg, ...args) => {
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  let fn = Symbol();
  thisArg[fn] = this;
  const res = thisArg[fn](...args);
  delete thisArg[fn];
  return res;
};
// 同理
Function.prototype._myapply = (thisArg, args = []) => {
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  let fn = Symbol();
  thisArg[fn] = this;
  const res = thisArg[fn](...args);
  delete thisArg[fn];
  return res;
};
// 同理
Function.prototype._mybind = (thisArg, ...args) => {
  let fn = this;
  return (...args) => {
    return fn._myCall(thisArg, ...args);
  };
};
//最好使用symbol进行处理一下,以及对于apply传递的数组考虑一下为空的情况

收到,已改正,感谢

@kangkang123269
Copy link

Function.prototype.myCall = function(context, ...args) {
  context = context || window;
  const fn = Symbol();
  context[fn] = this;
  const result = context[fn](...args);
  delete context[fn];
  return result;
}

Function.prototype.myApply = function(context, args) {
  context = context || window;
  const fn = Symbol();
  context[fn] = this;
  const result = context[fn](...args);
  delete context[fn];
  return result;
}

Function.prototype.myBind = function(context, ...args) {
  const self = this;
  return function(...args2) {
    return self.apply(context, args.concat(args2));
  }
}

@xudaotutou
Copy link

用Object.create继承context也许可以避免污染原来的context

@YMnotafraid
Copy link

Function.prototype.myapply = function (context, args) {
  context = context || window;
  args = args || [];
  const key = Symbol();
  context[key] = this;
  const res = context[key](...args); //扩展运算符对参数进行深拷贝的浅层拷贝
  delete context[key];
  return res;
};
Function.prototype.mycall = function (context, ...args) {
  context = context || window;
  args = args || [];
  const key = Symbol();
  context[key] = this;
  const res = context[key](...args);
  delete context[key];
  return res;
};
Function.prototype.mybind = function (context, ...args) {
  let self = this;
  args = args || [];
  return function (...newargs) {
    const key = Symbol();
    context[key] = self;
    const res = context[key](...args, ...newargs);
    delete context[key];
    return res;
  };
};

@Bbbtt04
Copy link

Bbbtt04 commented Mar 12, 2023

Function.prototype.myCall = function (context, ...args) {
  context = context || window
  args = args || []
  const key = new Symbol()
  context[key] = this
  const res = context[key](...args)
  delete context[key]
  return res
}
Function.prototype.myApply = function (context, args) {
  context = context || window
  args = args || []
  const key = new Symbol()
  context[key] = this
  const res = context[key](...args)
  delete context[key]
  return res
}
Function.prototype.myBind = function (context, ...args) {
  let self = this
  args = args || []
  return function (...newargs) {
    const key = Symbol()
    context[key] = self
    const res = context[key](...args, ...newargs)
    delete context[key]
    return res
  }
}

@cscty
Copy link

cscty commented Jun 17, 2023

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

@601odd
Copy link

601odd commented Sep 4, 2023

前面有一个bind写错了
Function.prototype._mybind = (thisArg, ...args) => {
let fn = this;
return (...args) => {
return fn._myCall(thisArg, ...args);
};
};
======================================>
Function.prototype._mybind = function (thisArg, ...arg1) {
let fn = this
return function (...arg2) {
return fn._myCall(thisArg, ...arg1, ...arg2)
}
}

@luckymore
Copy link

image
💯 仍然是不太严谨,原始类型值作为 context时,需要转为对象

Function.prototype.myCall = function(context, ...args) {
  context = (context === undefined || context === null) ? window : context
  if (Object(context) !== context) {
    context = Object(context)
  }
  context.fn = this
  const result = context.fn(...args)
  delete context.fn
  return result
}

function add(params) {
  return this.a + params
}

console.log(add.myCall(0, 2))
console.log(add.call(0, 2, 3, 4))

@luckymore
Copy link

luckymore commented Nov 8, 2023

apply的话,第二个参数要求类数组,为 null 的话要不报错,边界条件比较多 😢
image

Function.prototype.myApply = function(context, args = []) {
  context = (context === undefined || context === null) ? globalThis : context
  if (Object(context) !== context) {
    context = Object(context)
  }
  args = args === null ? [] : args
  if (!Array.isArray(args)) {
    args = Array.from(args)
  }
  context.fn = this
  const result = context.fn(...args)
  delete context.fn
  return result
}

// test case
const array = ["a", "b"];
const elements = [0, 1, 2];
array.push.myApply(array, 0);
console.log('myApply', array);
console.log('myApply', Math.max.myApply(null, null))
console.log('apply', Math.max.apply(null, null))

@luckymore
Copy link

luckymore commented Nov 9, 2023

这个更复杂点,只因规范要求 如果使用 new 运算符构造绑定函数,则忽略该值(指context参数)。
image
参考 core-js 的实现,并用 es6 语法简化

Function.prototype.myBind = function (that, ...partArgs) {
  var F = this
  var Prototype = F.prototype
  var boundFunction = function bound(...newArgs) {
    var args = [...partArgs, ...newArgs]
    /**
     * 若被 new 调用时,this 为即将生成的实例 bound,走 new F(...)
     */
    return this instanceof boundFunction ? new F(...args) : F.myApply(that, args)
  }
  if (Prototype && typeof Prototype === 'object') boundFunction.prototype = Prototype
  return boundFunction
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests