call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数git
上面是 call 的定义,apply 与 call 相似只是第二个参数是一个数组而 call 接收的则是一个参数列表。github
看一个例子数组
var obj = {
name: "obj"
};
function foo() {
return this.name;
}
foo.call(obj); //obj
复制代码
上面经过 call 改变了 this 的指向,下面就是模拟实现app
call 和 apply 是 es5 的方法,既然是模拟实现那确定不能用 es5 方法了,咱们先分析一下怎么来指定 this,this 跟动态做用域相似是在执行时肯定,那咱们在指定 this 的属性上添加一个方法而且执行,那么这个方法的 this 就是指定 this函数
var obj = {
name: "obj",
foo: function foo() {
return this.name;
}
};
obj.foo();
复制代码
上面解决了this,下面来看下怎么实现参数的传递,call 方法能够传递任意参数列表,咱们能够经过arguments
来获取,它是一个类数组。测试
function getName() {
console.log(arguments); //Arguments(5) [1, 2, 3, 4, 5]
}
function foo() {
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push("arguments[" + i + "]");
}
eval("getName(" + args + ")");
}
foo(1, 2, 3, 4, 5);
复制代码
OK,这两块已经搞定了,下面就是实现ui
Function.prototype.calls = function(con) {
con.fn = this;
// 获取参数
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push("arguments[" + i + "]");
}
var result = eval("con.fn(" + args + ")");
delete con.fn;
return result;
};
复制代码
上面删除属性是为了不污染,这里的fn
能够是任意属性名只要保证不重复就好了,不过仔细观察上面函数仍是有问题this
null
或者 undefined
;Function.prototype.calls = function(con) {
if (con == null) {
con = typeof window === "object" ? window : global;
}
con = Object(con);
con.fn = this;
// 获取参数
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push("arguments[" + i + "]");
}
var result = eval("con.fn(" + args + ")");
delete con.fn;
return result;
};
复制代码
测试一下es5
function foo() {
return this.length;
}
console.log(foo.calls("obj")); // 3
复制代码
撒花,这样就实现了 callspa
与 call 十分相似,这里就直接贴代码了
Function.prototype.applys = function(con, arr) {
if (con == null) {
con = typeof window === "object" ? window : global;
}
con = Object(con);
con.fn = this;
var result;
if (typeof arr === "object" && arr.length) {
var args = [];
for (var i = 0; i < arr.length; i++) {
args.push("arr[" + i + "]");
}
result = eval("con.fn(" + args + ")");
} else {
result = eval("con.fn()");
}
delete con.fn;
return result;
};
复制代码