call
call() 方法在使用一个指定的this值和若干个指定的参数的前提下调用某个函数或方法。
1 | var foo = { |
注意到两点:
- call改变的this的指向,最开始this指向的是window,call之后this指向了foo
- bar函数执行了
模拟实现第一步
1 | var foo = { |
这个时候this就指向了foo,但是这样做就给foo对象本身添加了一个属性,这样是不行的。
这个时候就可以想到,不要那就delete它不就可以了吗
这里列出了模拟的步骤:
将函数设为对象的属性
foo.fn = function(){}
执行函数
foo.fn()
删除该函数
delete foo.fn
这里我们把这些步骤封装在Function的原型上的一个call2函数里面
1
2
3
4
5
6
7
8
9
10
11
12
13Function.prototype.call2 = function(context){
context.fn = this;
context.fn();
delete context.fn;
}
var foo = {
value : 1
}
var bar = function(){
console.log(this.value)
}
bar.call2(foo); // 1
模拟实现第二步
call函数不仅能改变this的指向,而且还能传递参数
1. 我们可以通过循环处理arguments来获取到传递进来的参数
2. 通过eval函数执行字符串代码
1 | Function.prototype.call2 = function(context){ |
模拟第三步
目前代码已经完成了80%,还有一些需要注意的地方
- this 参数可以传null
- 函数是可以有返回值的!
例如使用call时:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18var obj = {
value: 1
}
function bar(name, age) {
return {
value: this.value,
name: name,
age: age
}
}
console.log(bar.call(obj, 'kevin', 18));
// Object {
// value: 1,
// name: 'kevin',
// age: 18
// }
处理思路:return出去 eval()的返回值
1 | Function.prototype.call2 = function(context) { |
apply的模拟实现
apply和call类似,唯一的区别就是参数是数组形式传递的
1 | Function.prototype.apply = function (context, arr) { |