前端面试题之JS手写apply
参考之前手写的call方法:
https://blog.csdn.net/qq593249106/article/details/83115935
Function.prototype.call2 = function (obj) {
var obj = obj || window;
var args = [];
for(var i = 1; i < arguments.length; i++) {
args.push('arguments[' + i + ']');
}
obj.fn = this;
var result = eval('obj.fn('+args+')');
delete obj.fn;
return result;
};
观察call和apply:
func.call(thisArg, arg1, arg2, arg3…)
func.apply(thisArg, [argsArray])
call和apply的区别就是,apply参数是以数组的形式传的,可以看看下面这个例子
var value = 'v in window';
function func() {
arguments = [].splice.call(arguments, 0); //这一句是把参数转成数组,因为arguments不是数组,输出的时候容易观察
console.log(arguments);
console.log(this.value);
}
var obj = {
value: 'v in obj'
};
func.call(obj, 1,2,3);
//[1, 2, 3]
//v in obj
func.apply(obj, [1,2,3]);
//[1, 2, 3]
//v in obj
之前手写call的操作是把参数整合成数组args:
var args = [];
for(var i = 1; i < arguments.length; i++) {
args.push('arguments[' + i + ']');
}
然而apply是直接传进来一个参数,省去了整合过程,直接把arguments[1]放进去:
var result = eval('obj.fn('+arguments[1]+')'); //arguments[1]是func.apply2(obj, [1,2,3])的[1,2,3]
再处理一下不传参的情况:
if(!arguments[1]) {
result = obj.fn;
}else {
result = eval('obj.fn('+arguments[1]+')');
}
最终代码:
var value = 'v in window';
function func() {
arguments = [].splice.call(arguments, 0); //这一句是把参数转成数组,因为arguments不是数组,输出的时候容易观察
console.log(arguments);
console.log(this.value);
}
var obj = {
value: 'v in obj'
};
Function.prototype.apply2 = function (obj) {
var obj = obj || window;
obj.fn = this;
var result;
if(!arguments[1]) {
result = obj.fn;
}else {
result = eval('obj.fn('+arguments[1]+')');
}
delete obj.fn;
return result;
};
func.apply(obj);
//[]
//v in obj
func.apply(obj, [1,2,3]);
//[1,2,3]
//v in obj
func.apply2(obj);
//[]
//v in obj
func.apply2(obj, [1,2,3]);
//[1,2,3]
//v in obj