call 实现
语法:
fun.call(thisArg, arg1, arg2, ...)
参数:
thisArg
- 在 fun 函数运行时指定的 this 值。if(thisArg == undefined|null) this = window,if(thisArg == number|boolean|string) this == new Number()|new Boolean()| new String()
arg1, arg2, ...
- 指定的参数列表。
Function.prototype.call2 = function (thisArg) {if (thisArg === undefined || thisArg === null) {thisArg = window;} else {switch (typeof thisArg) {
case 'number':
thisArg = new Number();
break;
case 'boolean':
thisArg = new Boolean();
break;
case 'string':
thisArg = new String();
break;
}
}
thisArg.fn = this;
let result;
if (arguments.length <= 1) {result = thisArg.fn();
} else {let args = [];
for (let i = 1; i < arguments.length; i++) {args.push('arguments[' + i + ']');
}
result = eval(`thisArg.fn(${args})`)
}
delete thisArg.fn;
return result;
}
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {Product.call2(this, name, price);
this.category = 'food';
}
function Toy(name, price) {Product.call2(this, name, price);
this.category = 'toy';
}
var cheese = new Food('feta', 5);
console.log('cheese:', cheese);
var fun = new Toy('robot', 40);
console.log('fun:', fun);
apply 实现
语法:
func.apply(thisArg, [argsArray])
参数:
thisArg
- 可选的。在 func 函数运行时使用的 this 值。请注意,this 可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。
argsArray
- 可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从 ECMAScript 5 开始可以使用类数组对象。浏览器兼容性 请参阅本文底部内容。
Function.prototype.apply2 = function (thisArg, argsArray) {
thisArg = thisArg || window;
thisArg.fn = this;
let result;
if (!argsArray) {result = context.fn();
} else {var tempArgs = [];
for (var i = 0, len = argsArray.length; i < len; i++) {tempArgs.push('args[' + i + ']');
}
result = eval(`thisArg.fn(${tempArgs})`)
}
delete thisArg.fn;
return result;
}
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {Product.apply2(this, [name, price]);
this.category = 'food';
}
function Toy(name, price) {Product.apply2(this, [name, price]);
this.category = 'toy';
}
var cheese = new Food('feta', 5);
console.log('cheese:', cheese);
var fun = new Toy('robot', 40);
console.log('fun:', fun);
总结
实现难点:
- 需要考虑传入的 thisArg 的多种类型
- 将函数设置成 thisArg 的属性,来实现 this 的绑定,调用完成后需要 delete 该属性
- 使用 eval 来实现需要传参给该函数的情况