-
Notifications
You must be signed in to change notification settings - Fork 0
/
test03.js
74 lines (72 loc) · 2.09 KB
/
test03.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
* @description
* 实现 call, apply, bind
*/
function test01() {
/**call */
Function.prototype.myCall = function (context) {
// 判断调用对象
if (typeof this !== 'function') {
throw new Error('Type error')
}
// 首先获取参数
let args = [...arguments].slice(1)
let result = null
// 判断 context 是否传入,如果没有传就设置为 window
context = context || window
// 将被调用的方法设置为 context 的属性
// this 即为我们要调用的方法
context.fn = this
// 执行要被调用的方法
result = context.fn(...args)
// 删除手动增加的属性方法
delete context.fn
// 将执行结果返回
return result
}
function fn() {
console.log(this.name, ...arguments)
}
fn.myCall({ name: 'lily' })
fn.call({ name: 'lily' })
/**apply */
Function.prototype.myApply = function (context) {
if (typeof this !== 'function') {
throw new Error('Type error')
}
let result = null
context = context || window
// 与上面代码相比,我们使用 Symbol 来保证属性唯一
// 也就是保证不会重写用户自己原来定义在 context 中的同名属性
const fnSymbol = Symbol()
context[fnSymbol] = this
// 执行要被调用的方法
const args = arguments[1] ? [...arguments[1]] : []
result = context[fnSymbol](...args)
// 删除手动增加的属性方法
delete context[fnSymbol]
return result
}
fn.myApply({ name: 'apply' }, [1, 2, 3])
fn.apply({ name: 'apply' }, [1, 2, 3])
fn.myApply({ name: 'apply' })
/**bind */
Function.prototype.myBind = function (context) {
// 判断调用对象是否为函数
if (typeof this !== 'function') {
throw new Error('Type error')
}
// 获取参数
const args = [...arguments].slice(1)
const fn = this
return function Fn() {
return fn.apply(
this instanceof Fn ? this : context,
// 当前的这个 arguments 是指 Fn 的参数
args.concat(...arguments)
)
}
}
fn.myBind({ name: 'bind' }, 1, 2, 3)(4)
}
test01()