call
Function.prototype.myCall = function(thisArg, ...restParams) {
thisArg = thisArg ?? window;
const self = Object(thisArg);
self.fn = this;
const result = self.fn(...restParams);
delete self.fn;
return result;
};
function sum(num1, num2){
console.log(this);
return num1 + num2;
};
sum();
sum.myCall();
sum.myCall({});
sum.myCall(1)
sum.myCall(null);
sum.myCall(undefined);
console.log(sum.myCall('...args', 18, 22));
apply
Function.prototype.myApply = function(thisArg, arrParams = []) {
thisArg = thisArg ?? window;
const self = Object(thisArg);
self.fn = this;
const result = self.fn(...arrParams);
delete self.fn;
return result;
};
function sum(num1, num2) {
console.log(this);
return num1 + num2;
};
sum();
sum.myApply();
sum.myApply([]);
sum.myApply(false);
sum.myApply(null);
sum.myApply(undefined);
console.log(sum.myApply('args', [2, 8]));
bind
Function.prototype.myBind = function(thisArg, ...args) {
thisArg = thisArg ?? window;
const self = Object(thisArg);
self.fn = this;
return (...restParams) => {
const result = self.fn(...[...args, ...restParams]);
delete self.fn;
return result;
};
};
function sum(num1, num2) {
console.log(this);
return num1 + num2;
};
sum();
sum.myBind()();
const newSum = sum.myBind('test', 20, 30);
console.log(newSum());
console.log(sum.myBind('苏苏', 20)(30));
console.log(sum.myBind('苏苏')(20, 30));
以上不考虑 edge case.
为什么不直接使用arguments?
因为现在已经不推荐使用arguments
并且箭头函数中并没有arguments
你可能会说或会想:你骗人我log了箭头函数中明明是有arguments的
你错了!因为箭头函数没有自己的作用域当你log一个不存在的变量时就会去上层作用域找
所以本质上你log看见的并不是箭头函数自己的arguments
还有些人可能会说你这说的也不对啊我log直接就是报错的说没有arguments啊(上层也没有)
我告诉你因为你们运行js的环境不一样 node 环境中全局作用域是有arguments的而浏览器没有
并且arguments得到的不是本质上的数组而是个对象数组
这有什么关系呢?
这关系可就大了代表你不能直接使用数组的方法而需要自己先做一遍处理
怎么处理呢?
one: 手动处理
Array.prototype.mySlice = function(start = 0, end) {
const arr = this;
end = end || arr.length;
const newArr = [];
for(let i = start; i < end; i++) {
newArr.push(arr[i]);
};
return newArr;
};
(function(){
console.log(arguments);
console.log(Array.prototype.mySlice.apply(arguments));
console.log(Array.prototype.mySlice.call(arguments, 1, 2));
console.log([].mySlice.call(arguments));
console.log([].mySlice.apply(arguments, [1, 2]));
}(1,2,3,5,8,13,21));
two: 自动处理
(function(){
console.log(arguments);
console.log([...arguments]);
console.log([].slice.call(arguments));
console.log(Array.from(arguments));
}(1,2,3,5,8,13,21));
一个不小心又带大家实现了一个slice
但总之我想说的是以后开发中请不要使用arguments如有不确定参数的需求请使用 剩余参数fn(...xxx)
请记住箭头函数中没有 arguments 但是可以使用剩余参数(可能也会避免闭包)