forked from zzzzzhowie/practical-javascript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbind.js
More file actions
64 lines (51 loc) · 1.75 KB
/
bind.js
File metadata and controls
64 lines (51 loc) · 1.75 KB
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
const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && obj !== null
// 实现一个简易的bind
const selfBind = function (bindTarget, ...args1) {
if (typeof this !== 'function') throw new TypeError('Bind must be called on a function')
let func = this
let boundFunc = function (...args2) {
let args = [...args1, ...args2]
// 使用new关键字调用返回新对象
if (new.target) {
let res = func.apply(this, args)
//如果构造函数返回一个对象则返回这个对象
if (isComplexDataType(res)) return res
//否则返回新建的对象
return this
} else {
func.apply(bindTarget, args)
}
}
// 绑定后的函数继承绑定前的函数(非箭头函数)
/**真正的bind创建的函数是没有prototype的,但是使用new会将创建的对象连接到bind前函数的prototype(非箭头函数)**/
this.prototype && (boundFunc.prototype = Object.create(this.prototype))
// 定义绑定后函数的长度和名字
let desc = Object.getOwnPropertyDescriptors(func)
Object.defineProperties(boundFunc, {
length: desc.length,
name: Object.assign(desc.name, {
value: `bound ${desc.name.value}`
})
})
return boundFunc
}
Function.prototype.selfBind || (Object.defineProperty(Function.prototype, 'selfBind', {
value: selfBind,
enumerable: false,
configurable: true,
writable: true
}))
function func() {
this.name = 'yeyan1996'
return {}
}
let example = {
age: 22
}
let boundFunc = func.selfBind(example)
console.dir(func)
console.dir(boundFunc)
boundFunc()
console.log(example)
let x = new boundFunc()
console.log(x)