11、函式內部的this指向以及如何改變函式內部的this指向
阿新 • • 發佈:2020-08-09
一、函式內部的this指向
呼叫方式 | this指向 |
普通函式呼叫 | window |
建構函式呼叫 | 例項物件 |
物件的方法呼叫 | 該方法所屬物件 |
事件繫結方法 | 繫結事件物件 |
定時器函式 | window |
立即執行函式 | window |
1、普通函式呼叫
普通函式的this指向window1 function fun() { 2 console.log('普通函式的this' + this); 3 } 4 fun();
2、建構函式呼叫
建構函式this指向ldh這個例項物件,原型物件裡面的this指向的也是ldh這個物件
1 function Star() {}; 2 Star.prototype.sing = function() {}; 3 var ldh = new Star();
3、物件的方法呼叫
物件的方法的this指向的是物件o
1 var o = { 2 sayHi: function() { 3 console.log('物件方法的this' + this); 4 } 5 } 6 o.sayHi();
4、事件繫結方法
繫結事件函式this指向的是函式的呼叫者btn這個按鈕物件
1 var btn = document.querySelector('button'); 2 btn.onclick = function() { 3 console.log('繫結事件函式的this' + this); 4 5 }
5、定時器函式
定時器函式this指向的是window
1 setTimeout(function() { 2 console.log('定時器函式的this' + this); 3 }, 1000);
6、立即執行函式
立即執行函式this指向的是window
1 (function(){ 2 console.log('立即執行函式的this'+this); 3 })();
二、改變函式內部的this指向的三種方法
1、call方法
call()方法可以呼叫函式,還可以改變函式內的this指向,它的主要作用是可以實現繼承
fun.call(thisArg,arg1,arg2,....)
這裡將fun函式的this指向o
1 var o = { 2 name: 'Andy' 3 } 4 5 function fun(a, b) { 6 console.log(this); 7 console.log(a + b); 8 } 9 fun.call(o, 1, 2);
將父建構函式裡的this指向子建構函式的例項物件(建構函式的this指向它的例項物件)
1 function Father(uname, age, sex) { 2 this.uname = uname; 3 this.age = age; 4 this.sex = sex; 5 } 6 7 function Son(uname, age, sex) { 8 Father.call(this, uname, age, sex); 9 } 10 var son = new Son('ldh', 18, 'male'); 11 console.log(son);
2、apply方法
fun.apply(thisArg,[argsArray])(傳遞的值必須包含在數組裡)
apply()方法可以呼叫函式,還可以改變函式內的this指向,但它的引數必須是陣列(偽陣列)
1 var arr = [1, 33, 22, 44, 12]; 2 var max = Math.max.apply(Math, arr); 3 var min = Math.min.apply(Math, arr); 4 console.log(max, min);
3、bind方法(用的最多)
bind()方法不會呼叫函式,但是可以改變函式內部this指向
fun.bind(thisArg,arg1,arg2,....)
1 var o = { 2 name: 'Andy' 3 } 4 5 function fun(a, b) { 6 console.log(this); 7 console.log(a + b); 8 } 9 var f = fun.bind(o, 1, 2); 10 f();
下面的小案例是點選按鈕後按鈕禁用,直到三秒後開啟按鈕
雖然定時器函式裡的this指向window,但是bind(this)裡面的this是在定時器函式的外面繫結的,這個this又在btns[i].onclick這個函式裡面,所以這個this指向的就是btns物件
為什麼這裡的this.disabled的this不用btns[i]呢,因為定時器是在3秒後執行,而for迴圈立馬執行,這裡有三個按鈕,則i為3
1 var btns = document.querySelectorAll('button'); 2 for (var i = 0; i < btns.length; i++) { 3 btns[i].onclick = function() { 4 this.disabled = true; 5 setTimeout(function() { 6 this.disabled = false; 7 }.bind(this), 3000); 8 } 9 }
3、call、apply、bind總結
相同點:都可以改變函式內部的this指向
區別:
1.call和apply會呼叫函式,並且改變函式內部的this指向
2.call和apply傳遞的引數不一樣,apply必須以陣列形式
3.bind不會呼叫函式,但是會改變函式內部的this指向
主要應用場景:
1.call主要用作繼承
2.apply經常跟陣列有關,比如藉助數學物件實現陣列中的最大最小值
3.bind可用於改變定時器內部的this指向