手写call,apply,bind函数

  目录

手写call,apply,bind函数

手写call,apply,bind函数

call

1
2
3
4
5
6
7
8
Function.prototype.myCall = function(context) {
context = context || window;
var arg = Array.prototype.slice.call(arguments, 1);
context.fn = this;
var result = context.fn(...arg);
delete context.fn;
return result;
}

测试

1
2
3
4
5
6
7
8
var testObj = {
name: 123
}
function testFn(a,b,c) {
console.log(this, a, b, c);
return 555;
}
testFn.myCall(testObj, 1, 2, 3);

apply

1
2
3
4
5
6
7
8
Function.prototype.myApply = function(context) {
context = context || window;
var arg = arguments[1];
context.fn = this;
var result = context.fn(...arg);
delete context.fn;
return result;
}

测试

1
2
3
4
5
6
7
8
var testObj = {
name: 123
}
function testFn(a,b,c) {
console.log(this, a, b, c);
return 555;
}
testFn.myApply(testObj, [1, 2, 3]);

bind

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Function.prototype.myBind = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
let _this = this
let args = [...arguments].slice(1)
return function F() {
// 判断是否被当做构造函数使用
if (this instanceof F) {
return _this.apply(this, args.concat([...arguments]))
}
return _this.apply(context, args.concat([...arguments]))
}
}

测试

1
2
3
4
5
6
7
8
var testObj = {
name: 123
}
function testFn(a,b,c) {
console.log(this, a, b, c);
return 555;
}
testFn.myBind(testObj, 1)(2, 3);

以上就是我们常用的call,apply,bind函数的手写实现,但是,用到了es6的[…arg]结构语法,下面只写一个call实现的es5版本。

call es5版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Function.prototype.myCall = function(context) {
context = context || window;
var arg = Array.prototype.slice.call(arguments, 1);
context.fn = this;
var fnStr = `context.fn(`;
for(var i=0, len=arg.length; i<len; i++) {
if(i === (len-1)) {
fnStr += arg[i];
}else {
fnStr += arg[i] + ',';
}
}
fnStr += ')';
console.log(fnStr);
var result = eval(fnStr);
delete context.fn;
return result;
}

测试

1
2
3
4
5
6
7
8
var testObj = {
name: 123
}
function testFn(a,b,c) {
console.log(this, a, b, c);
return 555;
}
testFn.myCall(testObj, 1, 2, 3);