JS之call,apply,bind

简易理解

猫吃鱼,狗吃肉,奥特曼打小怪兽。

有天狗想吃鱼了

猫.吃鱼.call(狗,鱼)

狗就吃到鱼了

猫成精了,想打怪兽

奥特曼.打小怪兽.call(猫,小怪兽)

或者 马云.赚钱.call(我)

this指向

this的指向在定义时是确定不了的,只有在执行时才会确定,指向调用它的那个函数。

call

实现思路:

  1. 将方法绑定在被改变的对象下
  2. 调用函数
  3. 删除对象下的函数
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
var obj = {
value: 'chjssg'
};
function foo(param1, param2) {
console.log(param1, param2)
console.log(this)
}

foo.call(obj, 'aaa', 'bbb') // chjssg

foo() // 浏览器环境下是window
console.log('---------------自实现call函数------------------')

Function.prototype.call2 = function (context) {
// context = context || window || {}
context = context || {}
console.log(this);
let arr = Array.from(arguments)
arr.shift()
context.fn = this;
context.fn(...arr);
delete context.fn
};

foo.call2(obj, 'param1', 'param2');

apply

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function fooo(name, sex) {
console.log(name,sex)
console.log(this.age)
}
var person = {
age: 18
}

fooo.apply(person, ["chj", "man"]);

console.log('---------------自实现apply函数------------------')
Function.prototype.apply2 = function (context) {
// context = context || window || {}
context = context || {}
var arr = arguments[1]
context.fn = this;
context.fn(...arr);
delete context.fn
};

fooo.apply2(person, ['chj', 'chinese-man'])

bind

bind() 方法会创建一个新函数。当这个新函数被调用时,
bind() 的第一个参数将作为它运行时的 this,
之后的一序列参数将会在传递的实参前传入作为它的参数

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
function foooo(param1, param2) {
console.log(param1, param2)
console.log(this.value)
return this.value
}
var obj1 = {
value: 'chjssgssg'
}
foooo.prototype.aaa = 'myfriend';

var fn = foooo.bind(obj1, 'wewe');

fn('aaa')
console.log('-----'+fn.aaa)
var newFn = new fn('aaa');
console.log(newFn.aaa)
// console.log(newFn)
// newFn('aaa', 'bbb')

console.log('---------------自实现bind函数------------------')

Function.prototype.bind2 = function (context) {
var self = this
var paramArr = Array.from(arguments)
paramArr.shift()
// if(paramArr.length==0) paramArr = null
return function() {
var param = [...paramArr ,...Array.from(arguments)]
console.log(param)
context = context || {}
return self.call(context, ...param)
}
};

var fn1 = foooo.bind2(obj1);
var result = fn1('chj', 'chj')
console.log(result)