关于bind的理解
MDN上的解释
bind()
函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体(在 ECMAScript 5 规范中内置的call属性)。当新函数被调用时this
值绑定到bind()
的第一个参数,该参数不能被重写。绑定函数被调用时,bind()
也接受预设的参数提供给原函数。一个绑定函数也能使用new
操作符创建对象:这种行为就像把原函数当成构造器。提供的this
值被忽略,同时调用时的参数被提供给模拟函数。
看如下的一个示例
var obj = {
age: 10,
getAge: function () {
return this.age;
}
}
console.log(obj.getAge()); //10
var getAge = obj.getAge;
console.log(getAge()); //undefined
第一次打印出了10
,但是第二次却是undefined
,这是由于第二次的上下文没有被保存的原因,所以this
指向了window
对象,然而window
上没有定义age
属性,所以返回了undefined
。
但是,如果使用bind
就可以轻松解决上下文保存的问题。
var getAge = obj.getAge.bind(obj);
console.log(getAge()); //10
不仅如此,bind
还可以传递多个参数,如果传递了2个或2个以上的参数,那么bind
会将第一个参数之后的值传递到绑定的函数参数中去。
var obj = {
age: 10,
getAge: function () {
console.log(Array.prototype.slice.call(arguments)); //[10, 11, 12]
return this.age;
}
}
var getAge = obj.getAge.bind(obj, 10, 11 ,12);
可以看到bind
中的值全部传递给了绑定函数。那么如果getAge
中也传递参数呢?
getAge(100); //[10, 11, 12, 100]
会将在函数中传递的参数向后移位。那么,这有什么用处呢?
有时候,某些函数的前几个参数已经内定了预设值,后面不用再改变了,就可以使用bind
传递,之后即使函数传参也不会对其造成影响。
最常见的场景是使用setTimeout
和setInterval
的时候,内部的函数this
总是指向window
,那么此时就可以使用bind
来解决这个问题。
当然,使用bind
还可以玩一些新花样,如下的这个例子是经典的闭包问题。
<ul>
<li>list1</li>
<li>list2</li>
<li>list3</li>
<li>list4</li>
<li>list5</li>
</ul>
<script>
var list = document.getElementsByTagName('li');
for (var i = 0; i < list.length; i++) {
list[i].onclick = function (i) {
console.log(i); //全部都会输出5
};
}
</script>
最常见的解决办法是使用闭包的方式。
for (var i = 0; i < list.length; i++) {
(function (i) {
list[i].onclick = function () {
console.log(i);
};
}(i));
}
那么使用bind
也可以解决这个问题
for (var i = 0; i < list.length; i++) {
list[i].onclick = function (i) {
console.log(i);
}.bind(list[i], i);
}
再举个例子,如果说我们要添加事件到多个节点,for 循环当然没有任何问题,我们还可以 “剽窃” forEach 方法:
var unboundForEach = Array.prototype.forEach,
forEach = Function.prototype.call.bind(unboundForEach);
forEach(document.querySelectorAll('input[type="button"]'), function (el) {
el.addEventListener('click', fn);
});
如果每隔1秒在控制台打印1-5怎么做呢?
for(var i = 1; i <= 5; i++) {
setTimeout(console.log.bind(console, i), i * 1000);
}
可以看到,bind
的玩法有很多,更多等着你去发现。
- 本博客所有文章除特别声明外,均可转载和分享,转载请注明出处!
- 本文地址:https://www.leevii.com/?p=1012