0%

call、apply、bind、new的手写

一、实现call函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Function.prototype.c = function(t) {
if (typeof this !== "function") {
throw new TypeError('Error')
}
//当传入的t为基础类型时,直接挂载fn会报错
if (typeof t !== 'object') {
t = new Object(t);
}
//t为可选参数,如果不传的话默认上下文为window
t = t || window
//给t创建一个fn属性,并将值设置为需要调用的函数
t.fn = this
//call可以传入多个参数作为调用函数的参数,所以需要将参数剥离出来
const args = [...arguments].slice(1)
const result = t.fn(...args)
//调用函数并将对象上的函数删除
delete t.fn
return result
}

二、实现apply函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function.prototype.a = function(t) {
if (typeof this !== "function") {
throw new TypeError('Error')
}
//当传入的t为基础类型时,直接挂载fn会报错
if (typeof t !== 'object') {
t = new Object(t);
}
//t为可选参数,如果不传的话默认上下文为window
t = t || window
//给t创建一个fn属性,并将值设置为需要调用的函数
t.fn = this
let r
//处理参数和call有区别
if (arguments[1]) {
r = t.fn(...arguments[1])
} else {
r = t.fn()
}
delete t.fn
return r
}

三、实现bind函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Function.protype.b = function(t) {
if (typeof this !== "function") {
throw new TypeError('Error')
}
const _this = this
const args = [...argument].slice(1)
//返回一个函数
return function F() {
if (this instanceof F) {
//对于new的情况,不会被任何方式改变this,所以对于这种情况我们需要忽略传入的this
return new _this(..args, ...arguments)
} else {
//直接调用,使用apply,因为bind可以实现柯里化,f.find(obj,1)(2),所以需要将两边的参数拼接起来
return _this.apply(t, args.concat(...arguments))
}
}
}

四、实现一个new

1
2
3
4
5
6
7
8
9
10
11
12
function create() {
//新生成一个对象
let obj = {}
//获取构造函数
let Con = [].shift.call(arguments)
//链接到原型
obj.__proto__ = Con.prototype
//绑定this并执行构造函数
let result = Con.apply(obj, arguments)
//确保返回值为对象
return result instanceof Object ? result : obj
}
  • 本文作者: David Xue
  • 本文链接: https://xdw-h.github.io/1/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!