JavaScript是一门非常灵巧的面向对象的开发语言,函数作为“第一公民”有很多方面的特殊应用手段,比如bind、apply、call等方法函数,它们的使用方式、传递参数都是一样的,也有区别。通过它们的使用,在以后面向对象的开发、建模、多态应用上会有很好的表现手段。
不同的是:
bind:绑定this的指向,然后返回一个新函数,返回的对应方法不会立即执行,需要调用才执行
call、apply:改变this的指向,调用是立即执行的。
apply和call的不同点:
1、call:接收的参数是逐个传入的;
2、apply:接收的是参数数组。
注意:当第一个参数为null时,非严格模式下(默认情况),this指向window;严格模式("use strict"),this指向null。
举例:
//函数返回一个对象,包括给定参数的最大值、最小值、总和、平均值
var funcA=function(...arg){
var valRang={
max:0,
min:0,
total:0,
average:0
}
valRang.max=Math.max.call(null,...arg);
valRang.min=Math.min.call(null,...arg);
valRang.total=(function(){
var x=0;
for(var i=0;i<arguments.length;i+=1){
x=x+arguments[i];
}
return x;
})(...arg);
valRang.average=valRang.total/arguments.length;
return valRang;
}
console.log('---正常调用---');
console.log(funcA(11,23,59,67,91));
console.log('---使用call方法调用---');
console.log(funcA.call(this,11,23,59,67,91));
console.log('---使用apply方法调用---');
console.log(funcA.apply(null,[11,23,59,67,91]));
console.log('---使用bind方法调用---');
console.log(funcA.bind(null,11,23,59,67,91)());
输出结果图:
通过这些方法可以应用其他对象的函数方法。
console.log('---math的方法调用---');
console.log(Math.max(1,5,27,33,24));
console.log(Math.max.call(1,5,27,33,24));
console.log(Math.max.apply(null,[1,5,27,33,24]));
console.log('---数组的方法调用---');
var arrA=[2,13,49];
var arrB=['A','B'];
arrA.push(arrB);
console.log(arrA);
var arrA=[2,13,49];
var arrB=['A','B'];
arrA.push.call(arrA,arrB);
console.log(arrA);
var arrA=[2,13,49];
var arrB=['A','B'];
arrA.push.apply(arrA,arrB);
console.log(arrA);
var arrA=[2,13,49];
var arrB=['A','B'];
var arrC=arrA.concat(arrB);
console.log(arrC);
var arrA=[2,13,49];
var arrB=['A','B'];
var arrD=arrA.concat.apply(arrA,arrB);
console.log(arrD);
var arrA=[2,13,49];
var arrB=['A','B'];
var arrD=arrA.concat.call(arrA,arrB);
console.log(arrD);
var arrA=[2,13,49];
var arrB=['A','B'];
var arrD=arrA.concat.apply(arrA,arrB);
console.log(arrD);
var arrA=[];
var arrB=['A','B'];
var arrD=arrA.concat.apply(arrA,arrB);
console.log(arrD);
输出结果图:
在JavaScript编程当中很注重this指向问题,上面的例子只是表明了它们三者的一般应用,对于this指向不明显,下面的例子很清楚地显示了this的指向。
var a=1;
function funcA(){
var a=22;
console.log('this指向:' + this);
console.log(this.a + a);
}
function funcB(){
var a=33;
funcA();
}
console.log('-------------0');
funcB();
var funcC=new function(){
this.a=44;
}
console.log('-------------');
funcA.call(funcC);
funcA.apply(funcC);
funcA.bind(funcC)();
输出结果图:
从上面的例子就可以看出this指向的改变,下面的例子也反应了this的指向改变。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<div style="width: 200px;height: 100px;background-color: #eeeeee;" id=demo>
☆☆☆
</div>
</body>
<script>
var divID=document.getElementById('demo');
divID.onclick=function(){
var func=function(x){
console.log(this)
console.log(this.innerHTML+'|'+x)
}
func(1);
}
</script>
</html>
在DIV上面点击鼠标,显示结果图如下:
可以看到this指向的是window,如果改变代码:
var divID=document.getElementById('demo');
divID.onclick=function(){
var func=function(x){
console.log(this)
console.log(this.innerHTML+'|'+x)
}
func.call(this,1);
// func.apply(this,[1]);也可以
// func.bind(this,1)();也可以
}
输出结果则有改变:
绑定到了div。
当第一个参数为null时,非严格模式下(默认情况),没有具体指定那么就指向window;严格模式("use strict"),参数为null,那么this就指向null,这个好理解。