call、apply、bind区别
call(无数个参数):第一个参数:改变this指向;第二个参数:实参;使用后自动执行该函数。
apply(两个参数):第一个参数:变this指向;第二个参数:数组(里面为实参);使用时自动执行该函数。
bind(无数个参数):第一个参数:改变this指向;第二个参数:实参,返回值为一个新的函数;使用时需要手动调用下返回的新函数。
var name = '小张',age = 18;
var obj = {
name = '小王',
objName = this.age,
myFun:function(){
console.log(this.name+'年龄'+this.age);
}
}
obj.objAge; //18
obj.myFun(); //小王年龄undefined
var name = '小赵';
function nameFun(){
console.log(this.name)
}
nameFun(); //小赵
改变this指向
var name = '小张',age = 18;
var obj = {
name = '小王',
objName = this.age,
myFun:function(){
console.log(this.name+'年龄'+this.age);
}
}
var newObj = {
name:'张三',
age:99
}
obj.myFun.call(newObj); //张三年龄99
obj.myFun.apply(newObj); //张三年龄99
obj.myFun.bind(newObj)(); //张三年龄99
bind返回的是一个新的函数,必须调用才会被执行。
var name = '小张',age = 18;
var obj = {
name = '小王',
objName = this.age,
myFun:function(){
console.log(this.name+'年龄'+this.age,'来自"+from + '去往' + to);
}
}
var newObj = {
name:'张三',
age:99
}
obj.myFun.call(newObj,'成都','上海'); //张三年龄99,来自成都去往上海
obj.myFun.apply(newObj,['成都','上海']); //张三年龄99,来自成都去往上海
obj.myFun.bind(newObj,'成都','上海')(); //张三年龄99,来自成都去往上海
obj.myFun.bind(newObj,['成都','上海'])(); //张三年龄99,来自成都上海,去往undefined
1、call
语法:functionFun.call(thisArg,arg1,arg2,...)
用法:用来在调用函数时,临时替换一次函数内部的this。
参数:1、thisArg:调用时用来替换函数内部的this值。 2、arg1,arg2,...:指定的参数列表。
返回值:使用调用者提供的this值和参数调用该函数的返回值。若该方法没有返回值,则返回undefined
function calc(base,bonus1,bonus2){
console.log(`${this.ename}的总工资是:${base+bonus1+bonus2}`)
}
var obj = {
ename:'lili'
}
calc.call(obj,1000,1200,2300); //lili的总工资是4500
//错误写法:obj.calc(1000,1200,2300),因为calc这个方法在全局对象中存在,不在obj的原型链上
2、apply
语法:functionFun.apply(thisArg,arr)
用法:调用函数时,改变函数内部this指向
参数:1、thisArg:改变函数内部this指向。 2、arr:传入的参数,数组格式。
返回值:使用调用者提供的this值和参数调用该函数的返回值。若该方法没有返回值,则返回undefined
function calc(base,bonus1,bonus2){
console.log(`${this.name}的总工资是:${base+bonus1+bonus2}`)
}
let obj = {
ename:'张'
}
calc.apply(obj,[1000,2000,3000]); //长得总工资是:6000
apply和call相同点都是能临时替换一次函数中的this。只不过apply比call多一项功能---先打算数组为单个值,再分别传给函数实参。
3、bind
语法:var newfunctionFun = functionFun.bind(thisArg,arg1,arg2,...)
用法:创建一个和原函数一模一样的新函数,将新函数中的this永久替换为指定的对象
参数:1、thisArg:改变this指向; 2、arg1,arg2,... :指定的参数列表
返回值:使用调用者提供的this值和参数调用该函数的返回值。若该方法没有返回值则返回undefined
bind只创建新函数,不会改变原函数。
function calc(base,bonus1,bonus2){
console.log(`${this.name}的总工资是:${base+bonus1+bonus2}`)
}
let obj = {
ename:'张'
}
let lcalc = calc.bind(obj,10000);
//新函数 function lcalc(base,bonus1,bonus2){
// this.ename永久替换为obj.ename
// 形参base永久为10000
//}
//此后再调用lcalc时,无需反复.call(obj,10000),其中this指向永远指obj,base永远是10000
lcalc(2000,3000); //张的总工资是:15000
lcalc(1000,6000); //张的总工资是:17000
bind的一个重要区别是后面传入这个参数列表可以分次传入,call和apply必须一次性传入所有参数。
var arr = [1,10,5,8,12];
var max = Math.max.bind(null,arr[0],arr[1],arr[2],arr[3])
console.log(max(arr[4])); // 12 分两次传参
//bind方法可以分多次传参,最后函数运行时会把所有参数连接起来一起放入函数运行。
应用场景
1、数组之间追加
var arr = [12,'foo',{name:'Joe',-2548}];
var arr2 = ['Doe',555,100];
Array.prototype.push.apply(arr,arr2);
//[12,'foo',{name:'Joe',-2548},'Doe',555,100]
2、获取数组中的最大值和最小值
var numbers = [5,548,120,-215];
var maxInNumbers = Math.max.apply(Math,numbers); //548
minInNumbers = Math.max.call(Math,5,548,120,-215); //548
总结:
1、相同点:
- 都可以改变函数内部的this指向;
- 第一个参数都是自定函数内部中this的指向
2、区别:
1)一个函数被call/apply的时候会立即执行函数,bind不会调用函数,但bind会创建一个和原函数一模一样仅仅改变了this指向的新函数,然后在需要的时候调用新函数执行。
2)call/apply/bind传递的参数不通,call和bind调用时接收的是指定的参数列表,apply调用时接收的是一个数组,apply可以打散其接收到的数组成为单个值,再分别传给函数实参。