三个使用区别
- 都是用来改变函数的this对象的指向的;
- 第一个参数都是this要指向的对象;
- 都可以利用后续参数传参;
- bind是返回对应函数,便于稍后调用,apply、call是立即调用;
apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向);
如果使用apply或call方法,那么this指向他们的第一个参数,apply的第二个参数是一个参数数组,call的第二个及其以后的参数都是数组里面的元素,就是说要全部列举出来;
他们的常用用法:
1.数组之间的追加;
2.获取数组中的最大值和最小值,利用他们扩充作用域拥有Math的min和max方法;
由于没有什么对象调用这个方法,所以第一个参数可以写作null或者本身;
var numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers), //458 maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
3.验证是否是数组(前提是toString()方法没有被重写过)
function isArray(obj){
return Object.prototype.toString.call(obj)
=== '[object Array]' ;
}
4.让类数组拥有数组的方法
比如arguments对象,获取到的文档节点等,并没有数组的那些方法:
Array.prototype.slice.apply(argument);
//理论上来说这个比较快,直接在原型上查找slice方法
//但实际上比较慢
或者
[].slice.apply(arguments);
//理论上来说这个比较慢,因为要Array做一个实例化再查找slice方法
//实际上比较快,因为现在的各种自动化工具会把上一种方法转换为这种,而第二种代码比较简洁,所以会比较快;
bind()--也是改变函数体内this的指向;
bind会创建一个新函数,称为绑定函数,当调用这个函数的时候,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入bind()方法的第二个及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数;
bind与apply、call最大的区别就是:bind不会立即调用,其他两个会立即调用
下面来讲bind()函数,bind()是es5中的方法,他也是用来实现上下文绑定,看它的函数名就知道。bind()和call与apply不同。bind是新创建一个函数,然后把它的上下文绑定到bind()括号中的参数上,然后将它返回。
所以,bind后函数不会执行,而只是返回一个改变了上下文的函数副本,而call和apply是直接执行函数。
示例1 数学函数中的应用
const abc = [12,1,2,3,11,33,2222,112];
// console.log(Math.max.apply(null,abc));
// console.log(Math.max.apply(Math,abc));
// console.log(Math.max.apply(this,abc));
// console.log(Math.max.call(null,...abc));
// console.log(Math.max.call(Math,...abc));
// console.log(Math.max.call(this,...abc));
var a = {'0':'a', '1':'b', '2':'c', length:3}; // An array-like object
const str = '';
// console.log(a);
console.log([].slice.apply(a));
console.log(Object.prototype.toString(str));
console.log(Object.prototype.toString.call(str));
console.log(Math.max.bind(Math, abc));
示例2 防抖中应用apply
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.container {
width: 200px;
height: 200px;
background-color: #faa;
}
</style>
</head>
<body>
<div class="container" id="container"></div>
</body>
<script>
var count = 1;
var container = document.getElementById('container');
container.onmousemove = debunce(fun, 100);
function fun(e) {
console.log(e);
container.innerHTML = count++;
}
function debunce(func, wait) {
var timeout;
this.name = 'liang';
return function() {
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(
function() {
func.apply(context, args);
}, wait);
}
}
</script>
</html>