实现 apply 方法
# 实现 apply 方法
# 功能描述
apply()
方法调用一个具有给定 this
值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
apply()
该方法的语法和作用与 call()
方法类似,只有一个区别,就是 apply()
方法接受的是一个包含多个参数的数组,而 call()
方法接受的是一个参数列表。
基本用法如下:
// apply()
// 该方法能接收两个参数
// obj: 这个对象将代替 func 里 this 对象
// args: 这是一个数组,它将作为参数传给 func(args --> arguments)
func.apply(obj, args)
1
2
3
4
5
2
3
4
5
# 实现思路
实现 apply()
的思路 和 实现 call()
是一样的,只要把入参中的 ...args
换成 args
即可。
# 手写实现
/**
* context: 函数中的 this 将改变为指向这个参数
* args:传递给函数的实参信息
* this:在未改变指向时,指向要处理的函数 func
*/
Function.prototype.myApply = function(context, args) {
// null、undefined 和不传时,context为 window(注意是双等号不是三等号)
context = context == null ? window : context;
// 必须保证 context 是一个对象类型
let contextType = typeof context;
if (!/^(object|function)$/i.test(contextType)) {
context = Object(context);
}
let result;
let key = Symbol('key') // 成员名唯一,防止修改原始对象的值
context[key] = this; // 把函数作为对象的某个成员值(这里的这个 this 是待处理函数 func)
result = context[key](...args); // 此时的函数是对象中的属性,基于对象[成员]的方式执行函数,函数中的 this 指向就是对象
delete context[key]; // 设置的成员属性用完后要删除掉
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 测试用例
// 目标:调用方法时打印出 "张三 性别:男 年龄:13"
window.name = 'window';
let obj = { name: '张三' };
let func = function(sex, age){
console.log(this.name + ' 性别:' + sex + ' 年龄:' + age);
}
// 对比两个输出结果
func.apply(obj, ['男', 13]);
func.myApply(obj, ['男', 13]);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
(完)