call()、apply()、bind() 都是用來改變函數運行時的this指向!面試
也就是改變函數執行的上下文,被稱爲改變this指向的三兄弟。數組
先記住如下this的總結,便於如下例子中this指向的理解:markdown
經過一個demo來理解call( )的用法:app
var person = {
name:'leaf',
age:26,
getName:function(){
console.log(this.name+' '+this.age);
}
}
var person2 = {
name:'ice',
age:18
}
person.getName();//leaf 26
person.getName.call(person2);//ice 18
複製代碼
getName( )是person這個對象的一個方法,在方法中,this表示該方法所屬的對象,因此getName方法中的this指的是person這個對象。函數
call( )能夠改變this的指向,它能夠把getName方法所屬的對象指向person2。oop
因此:ui
call( )容許爲不一樣的對象分配和調用屬於一個對象的函數/方法。this
call( )方法能夠接受參數,第一個參數是改變上下文的對象,從第二個參數開始以參數列表的形式展現,用逗號隔開。spa
var person = {
name:'leaf',
age:26,
getName: function(country,city){
console.log(this.name + ' ' + this.age + ' ' + country + ' ' + city);
}
}
var person2 = {
name:'ice',
age:18
}
person.getName.call(person2, '英國','倫敦');//ice 18 英國 倫敦
複製代碼
var person = {
name:'leaf',
age:26,
getName:function(){
console.log(this.name+' '+this.age);
}
}
var person2 = {
name:'ice',
age:18
}
person.getName();//leaf 26
person.getName.apply(person2);//ice 18
複製代碼
apply( )方法接受數組形式的參數。code
var person = {
name: 'leaf',
age: 26,
city: '廣西',
country: '中國',
getName: function(country,city){
console.log(this.name + ' ' + this.age + ' ' + country + ' ' + city);
}
}
var person2 = {
name: 'ice',
age: 18
}
person.getName.apply(person2, ['美國','紐約']);//ice 18 美國 紐約
//等價於
// person.getName.call(person2, '英國','倫敦');//ice 18 英國 倫敦
複製代碼
總結:
apply( )和call( )方法很類似,那apply( )和call( )的區別主要在於參數的區別:
除了接受參數形式不一樣以外,call( )和apply( )行爲都是一致的。
bind() 方法一樣也是能夠改變this的指向,可是和call、apply不一樣的是bind( )返回的是改變上下文的一個函數,而且不會立刻執行,須要用的時候再執行。
var person = {
name:'leaf',
age:26,
getName:function(){
console.log(this.name+' '+this.age);
}
}
var person2 = {
name:'ice',
age:18
}
person.getName.bind(person2)();//ice 18
複製代碼
bind( )方法後邊多了個()外,結果和call、apply返回的結果都是一致!
總結:
bind方法返回的是一個新函數,必須調用它纔會被執行。
var name = 'qing',age = 20;
var person = {
name:'leaf',
personAge:this.age,
getName:function(){
console.log(this.name+' '+this.age);
}
}
var person2 = {
name:'ice',
age:18
}
person.getName.call(person2); //ice 18
person.getName.apply(person2); //ice 18
person.getName.bind(person2)(); //ice 18
複製代碼
var person = {
name: 'leaf',
age: 26,
city: '廣西',
country: '中國',
getName: function(country,city){
console.log(this.name + ' ' + this.age + ' ' + country + ' ' + city);
}
}
var person2 = {
name: 'ice',
age: 18
}
person.getName.call(person2, '英國','倫敦'); //ice 18 英國 倫敦
person.getName.apply(person2, ['美國','紐約']); //ice 18 美國 紐約
person.getName.bind(person2, '中國','上海')(); //ice 18 中國 上海
person.getName.bind(person2, ['中國','上海'])(); //ice 18 中國,上海 undefined
複製代碼
總結:
不傳參的狀況下,除bind方法後邊多個()外,返回的結果和call、apply都是同樣的。
傳參的狀況下,call、apply、bind第一個參數都是改變this的指向對象,主要差異在第二個參數:
call的參數以參數列表的形式直接存放,參數之間用逗號分隔;
apply的參數以數組的形式存放,參數必須放置在一個數組裏面;
bind的參數存放形式和call是同樣的,都是以參數列表的形式存放,參數直接用逗號分隔。
var arr = [7, 8, 2, 1, 4, 3, 5, 6, 0];
console.log(Math.max.apply(Math, arr)); //8
console.log(Math.max.call(Math, 7, 8, 2, 1, 4, 3, 5, 6, 0)); //8
console.log(Math.max.bind(Math, 7, 8, 2, 1, 4, 3, 5, 6, 0)()); //8
console.log(Math.max.call(Math, arr)); //NaN
複製代碼
求一個數組的最大或最小值,最方便的方法就是使用Math.max.apply方法。
注意:
在上邊的代碼中,由於不須要this去調用Math方法,apply的第一個參數能夠寫成null、underfined、window 、document均可以。
console.log(Math.max.apply(null, arr)); //8
複製代碼
那你可能會問Math.max( )原本就能夠求一組數中的最大值,那爲何不直接使用Math.max( )呢?
由於Math.max( )的參數只能是Number類型的參數,若是放置一個數組會報錯:
var arr = [7, 8, 2, 1, 4, 3, 5, 6, 0];
console.log(Math.max(arr)); //math is not defined
console.log(Math.max(7, 8, 2, 1, 4, 3, 5, 6, 0)); //8
console.log(Math.max(...arr));//8 也可使用擴展運算符,將數組轉換成Number類型的參數
複製代碼
而apply( )能夠直接接受一個數組,能夠將數組參數轉換成列表參數傳入,從而直接求數組的最大值。
最小值就不講了,和Math.max同樣的,直接Math.min替換Math.max便可。