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;
};
複製代碼