call()
经过指定this
的指向来实现函数的间接调用,而且能够传入函数调用的参数
数组
举个例子:bash
var foo = {
value: 1
};
function bar() {
console.log(this.value)
}
bar.call(foo); // 1
复制代码
首先咱们要知道call()
在这里起的做用:
闭包
咱们能够模拟一下这两个效果:app
var foo = {
value: 1,
bar: function() {
console.log(this.value)
}
};
foo.bar(); // 1
复制代码
能够看到将bar
设为foo
的属性,便实现了将this
指向foo
。可是这样作给foo
对象无缘无故的添加了一个属性,所以咱们还要经过delete
删除它。
所以主要实现思路以下:
函数
// 1.将函数设为对象的属性
foo.fn = bar
// 2.执行该函数
foo.fn()
// 3.从对象中删除该函数
delete foo.fn
复制代码
根据这个思路先实现一个简易版的:post
Function.prototype.call2 = function(context) {
// 首先要获取调用call的函数,用this能够获取
context.fn = this;
context.fn();
delete context.fn;
}
复制代码
接下来实现call
给定参数执行函数:
要注意传入的参数个数是不肯定的,咱们能够从arguments
对象中取值,即第二个到最后一个参数即是要传入的参数。测试
Function.prototype.call2 = function(context) {
context.fn = this;
var args = [];
// 遍历arguments类数组对象,取得第二个开始的参数,放到数组里面去
for(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
// 执行后 args为 [arguments[1], arguments[2], arguments[3]]
// 这里 args 会自动调用Array.toString()方法
eval('context.fn(' + args +')');
delete context.fn;
}
复制代码
此时call()
方法的核心已经实现了,下面要完善call()
的功能:
ui
window
完整实现this
Function.prototype.call2 = function(context) {
var context = context || window;
context.fn = this;
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
var result = eval('context.fn(' + args + ')');
delete context.fn
return result;
}
复制代码
// 测试
var value = 2;
var obj = {
value: 1
}
function bar(name, age) {
console.log(this.value);
return {
value: this.value,
name: name,
age: age
}
}
bar.call2(null); // 2
console.log(bar.call2(obj, 'kevin', 18));
// 1
// Object {
// value: 1,
// name: 'kevin',
// age: 18
// }
复制代码
apply的实现跟call相似,区别在于apply第二个参数传入的是一个参数数组spa
Function.prototype.apply = function (context, arr) {
var context = Object(context) || window;
context.fn = this;
var result;
if (!arr) {
result = context.fn();
}
else {
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')')
}
delete context.fn
return result;
}
复制代码
结尾
系列文章: