JS修改this指向有三種方法,call,bind,apply(這三個都是函數對象的方法,需要通過函數對象來調用,它們都是綁定在函數對象原型上面的方法),fun()是函數,則fun稱為函數對象,調用語法示例:fun.call()
一. call
1.call函數的作用是調用函數,並且修改這個函數的this指向調用的對象
fun.call(thisArg,arg1,arg2,……)
thisArg:表示當前函數的this要指向的對象
arg1,arg2,……:表示普通參數
call方法內部的執行: 1.首先把call里面的第一個實參設置為調用這個方法的對象 2.把call方法第二個及之后的實參獲取到 3.把要操作的函數執行,並且把第二個以后傳遞進來的實參傳遞給函數
例子1(一個參數):修改fn方法的調用對象為o,意思就是對象o調用了fn.
1 function fn(){ 2 console.log('i want go to wc!'); 3 console.log(this); 4 } 5 //call的作用: 6 //1.調用函數 7 fn.call();//此時this指向的是window 8 //2.調用函數並修改this指向 9 //首先聲明一個對象 10 var o ={ 11 name:'奧里給!' 12 } 13 fn.call(o);
運行結果:
例子2(多個參數):第一個參數意思為調用eat方法的對象,后面兩個表示參數傳入eat方法。
function eat(x,y){ console.log(x+y); } function drink(x,y){ console.log(x-y); } eat.call(drink,3,2); 輸出:5
2.利用call實現繼承
1 //父構造函數 2 function Father(name,age){ 3 //this指向父構造函數的對象實例 4 this.name = name ; 5 this.age = age; 6 } 7 //子構造函數 8 function Son(name,age){ 9 //調用父構造函數,並修改Father的this為兒子的this,以達到調用父方法 10 Father.call(this,name,18); 11 } 12 var wb = new Son('小王八',8) 13 console.log(wb);
運行結果:
二.apply
對於 apply、call 二者而言,作用完全一樣,只是接受參數的方式不太一樣。
語法格式:call(參數1,參數2,參數3),其中第一個參數為調用的對象
apply(參數1,[參數數組])
例子:fn.call(O,x,y) apply(O,[x,y])
function class1(args1,args2){ this.name=function(){ console.log(args,args); } } function class2(){ var args1="1"; var args2="2"; class1.call(this,args1,args2); /*或*/ //class1.apply(this,[args1,args2]); } var c=new class2(); c.name(); 輸出:1 2
三. bind
- bind:語法和call一模一樣,區別在於call立即執行,bind等待執行,bind是后面才有的,所以bind不兼容IE6~8
fn.call(obj, 1, 2); // 改變fn中的this,並且把fn立即執行 fn.bind(obj, 1, 2); // 改變fn中的this,fn並不執行
例子:this改變為obj了,但是綁定的時候立即執行,當觸發點擊事件的時候執行的是fn的返回值undefined
document.onclick = fn.call(obj);
bind會把fn中的this預處理為obj,此時fn沒有執行,當點擊的時候才會把fn執行
document.onclick = fn.bind(obj);
總結:call與apply都可以改變this指向,參數傳遞方式不一樣,都是立即調用函數,而bind用法與call一樣,只不過不會立即執行,而是返回一個函數。