foreword
Function binding is probably the least of your attention when using JavaScript, but when you realize you need a solution to how to keep this context in another function, what you really need is Actually Function.prototype.bind()
, it's just that you may still not realize it.
The first time you encounter this problem, you may be inclined to set this to a variable so that you can continue to refer to it after changing the context.
1. Syntax of bind
bind()
The main function of the method is to bind the function to an object, the bind()
method will create a function, and the value of the this object in the function body will be bound to bind()
the value of the incoming function.
1.1 Definitions
bind() is defined as follows:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
The bind() function creates a new function (called the bind function) with the same body as the called function (the target function of the bind function). When the target function is called the this value is bound to bind()
the first parameter of , which cannot be overridden.
1.2 Principle
bind()
The principle can be simulated with the following code :
1
2
3
4
5
6
|
Function.prototype.bind =
function
(context) {
var
self =
this
;
// 保存原函数
return
function
() {
// 返回一个新函数
return
self.apply(context, arguments);
// 执行新函数时,将传入的上下文context作为新函数的this
}
}
|
1.3 Syntax
1
|
Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
|
2. Application scenarios of bind
2.1 Implementing Object Inheritance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var
A =
function
(name) {
this
.name = name;
}
var
B =
function
() {
A.bind(
this
, arguments);
}
B.prototype.getName =
function
() {
return
this
.name;
}
var
b =
new
B(
"hello"
);
console.log(b.getName());
// "hello"
|
2.2 Event Handling
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var
paint = {
color:
"red"
,
count: 0,
updateCount:
function
() {
this
.count++;
console.log(
this
.count);
}
};
// 事件处理函数绑定的错误方法:
document.querySelector(
'button'
)
.addEventListener(
'click'
, paint.updateCount);
// paint.updateCount函数的this指向变成了该DOM对象
// 事件处理函数绑定的正确方法:
document.querySelector(
'button'
)
.addEventListener(
'click'
, paint.updateCount.bind(paint));
// paint.updateCount函数的this指向变成了paint
|
2.3 Time interval function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var
notify = {
text:
"Hello World!"
,
beforeRender:
function
() {
alert(
this
.text);
},
render:
function
() {
// 错误方法:
setTimeout(
this
.beforeRender, 0);
// undefined
// 正确方法:
setTimeout(
this
.beforeRender.bind(
this
), 0);
// "Hello World!"
}
};
notify.render();
|
2.4 Borrowing the native methods of Array
1
2
3
4
|
var
a = {};
Array.prototype.push.bind(a,
"hello"
,
"world"
)();
console.log(a);
// "hello", "world"
|
3. Browser compatibility of bind() method
4. Compatibility writing of bind()
1
2
3
4
5
6
7
8
9
10
11
12
|
if
(!Function.prototype.bind) {
Function.prototype.bind =
function
() {
var
self =
this
,
// 保存原函数
context = [].shift.call(arguments),
// 需要绑定的this上下文
args = [].slice.call(arguments);
// 剩余的参数转成数组
return
function
() {
// 返回一个新函数
// 执行新函数时,将传入的上下文context作为新函数的this
// 并且组合两次分别传入的参数,作为新函数的参数
return
self.apply(context, [].concat.call(args, [].slice.call(arguments)));
}
};
}
|
5. The difference between bind and call/apply methods
Common ground:
Can change the context of function execution;
difference:
bind: does not execute the function immediately, generally used for asynchronous calls and events; call/apply: executes the function immediately.