call
call 是在指定一个this 值与若干个参数值的情况下去调用一个函数(冴羽大大说的)call 方法实现
思路: 首先我们想调用一个函数func 在this指向一个对象的情况下
//需要被绑定的对象
var obj = {
name: 'van'
}
那么我们可以尝试将func绑定在obj上,然后去调用它,最后无情删除
obj.func = func; //绑定
obj.func(); //调用
delete obj.func; //删除
有了思路之后第一版call乞丐版就出来了
Function.prototype.call2 = function(context){
context.fn = this; //第一步绑定
context.fn(); //第二步 调用
delete context.fn; //第三步删除
}
var obj = {
value: 'van'
};
function test () {
console.log(this.value);
}
test.call2(obj); // van
到了这一步,我们已经实现了基本的使用call将this指向obj对象
但是我们知道,call是可以传参的,那么我们再来试一下传参这个功能实现
Function.prototype.call2 = function(context){
context.fn = this; //第一步绑定
var args = [];
for(var i=1;i < arguments.length;i++){
args.push('arguments[' + i + ']');
}
//此时args中的内容为 ['arguments[1]','arguments[2]']
//但是我们调用fn时怎么把args传进去呢,我们想到es6的eval函数了
//此时在eval中,args 自动调用 args.toString()方法,eval的效果如 jawil所说,最终的效果相当于
//context.fn(arguments[1],arguments[2],.....)
eval('context.fn(' + args + ')') //第二步 调用
delete context.fn; //第三步删除
}
var obj = {
value: 'van'
};
function test (name,age) {
console.log(name);
console.log(age);
console.log(this.value);
}
test.call2(obj,'van','20'); // van
到了现在我们已经接近成功了,最后我们想到了call 好像是可以传一个null值的,并且 还可以有返回值???
那我们再来修改一下代码
Function.prototype.call2 = function(context){
//判断context是否为null,如果为null则将他指向window
context = context || window;
context.fn = this; //第一步绑定
var args = [];
for(var i=1;i < arguments.length;i++){
args.push('arguments[' + i + ']');
}
//此时args中的内容为 ['arguments[1]','arguments[2]']
//但是我们调用fn时怎么把args传进去呢,我们想到es6的eval函数了
//此时在eval中,args 自动调用 args.toString()方法,eval的效果如 jawil所说,最终的效果相当于
//context.fn(arguments[1],arguments[2],.....)
var value = eval('context.fn(' + args + ')') //第二步 调用
delete context.fn; //第三步删除
return value;
}
var obj = {
value: 'van'
};
function test (name,age) {
console.log(name);
console.log(age);
console.log(this.value);
}
test.call2(obj,'van','20'); // van
此时我们终于完成了call的所有内容,淦,终于写完了
apply
apply 与call十分相似,他们的区别就是,call后面跟一大堆参数,而apply则只接收一个数组直接上最终代码
Function.prototype.apply2 = function(context,arr){
context = context || window;
context.fn = this;
var result;
if(!arr){
//没有参数的情况下
result = context.fn();
}
else{
var args = [];
for(var i = 1;i<arr.length;i++){
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')');
}
delete context.fn;
return result;
}