'JavaScript中的this'
1:基本概念
this字面意思是當前,當前執行代碼的環境對象或者是上下文。代表著當前方法執行的環境上下文,那麼何為環境上下文,通俗的說,誰調用了函數,誰就是這個函數的環境上下文。
在js中,this只有兩種指向,一種是指向當前的封閉作用域,或者是指向當前作用域的外層,this的最頂層就是window對象。
關於this必須要了解的是嚴格模式,嚴格模式是js裡面的一個子集,是具有限制性JavaScript變體,嚴格模式也是js的一種,但是加了一些限制。
比如:
- 在嚴格模式下通過拋出錯誤來消除了一些原有的靜默錯誤(靜默錯誤:語法有錯誤但是js並沒有提示,默認允許這個操作)。比如要取一個函數的傳入參數,在非嚴格模式下,可以直接拿到它的grument,但在嚴格模式下會拋出一個錯誤。
- 嚴格模式修復了一些導致JavaScript引擎難以執行優化的缺陷
- 禁用了在ECMAScript的未來版本中可能會定義的一些語法
進入"嚴格模式"的標誌:"use strict";
// 為整個腳本開啟嚴格模式
"use strict";
var v = "Hi! I'm a strict mode script!";
// 為函數開啟嚴格模式
function strict() {
'use strict';
function nested() {
return "And so am I!";
}
return "Hi! I'm a strict mode function! " + nested();
}
2:全局環境
在全局環境下,無論是否在嚴格模式下,在全局執行環境下(任何函數體外部)this指向全局對象。也就是說在全局執行環境,這個this永遠指向全局對象,這個全局對象在瀏覽器中就是window。
//瀏覽器環境
var name = 'Eric';
console.log(window.name === this.name); /* true */
console.log(window === this); /* true */
3:函數體內部
在函數體內部,this的值取決於函數被調用的方式。函數被調用的方式有很多種:
簡單調用,也就是說沒有添加任何額外的操作,沒有添加一個this的綁定或者是改變。
簡單調用分為嚴格模式與非嚴格模式。
- 在非嚴格模式下,this默認指向全局對象。
// 瀏覽器環境
function simple(){
return this;
}
console.log(simple() === window);
// true
- 在嚴格模式下,保持進入執行環境時的值,沒有指定時默認undefined。
// 瀏覽器環境
function simple2(){
"use strict";
return this;
}
simple2() === undefined;
// true
window.simple2() === window;
// true
this傳遞,在js中this綁定有兩種:
- 一種是call/apply,可以看作是一種,它們都是一個綁定this的立即執行的一個方法,綁定之後會立即執行這個函數,兩者的區別在於傳遞參數的不同,一個是傳一個參數,一個是傳一堆參數;call/apply實際上是綁定值的是一個對象,存在一個ToObject過程。call/apply是一個立即執行的綁定this的一個操作。
// 瀏覽器環境
var object = {
name: 'Eric'
};
var name = 'Iven';
function getName(arg) {
return this.name;
}
getName(); /* Iven */
getName.call(object); /* Eric */
getName.apply(object); /* Eric */
- 另一種是bind,與上面不同的是bind不會立即執行,它只是實現一個綁定的過程,返回的是一個柯里化的函數,這個柯里化的函數就是call/apply。bind只能被綁定一次。
name = 'Davy';
function bindThis(){
return this.name;
}
var getName1 = bindThis.bind({ name: "Eric" });
console.log(getName1()); /* Eric */
var getName2 = getName1.bind({ name: "Iven" });
console.log(getName2()); /* Eric */
箭頭函數在執行的時候會形成一個封閉的作用域,this與封閉作用域的this保持一致,call/apply/bind都將會被忽略。
// 瀏覽器環境
var globalThis = this;
var arrowsFunction = () => this;
console.log(arrowsFunction() === globalObject); /* true */
作為對象的方法被調用(有一個靠近原則):在對象裡面定義了一個函數,然後通過對象去調用這個函數。
// 瀏覽器環境
var object = {
name: 'Eric',
getName: function() {
return this.name;
}
};
console.log(object.getName()); /* Eric */
function getName2() {
return this.name;
}
object.getName = getName2;
console.log(object.getName()); /* Eric */
object.object = {
getName: getName2,
name: 'Iven'
};
console.log(object.object.getName()); /* Iven */
4:全局函數
- setTimeout
- setInterval
- alert
setInterval()方法用於在指定的毫秒數後調用函數或計算表達式。
語法:setTimeout(code,millisec),參數code必需,要調用的函數後執行的JavaScript代碼串;millisec必需,在執行代碼前等待的毫秒數。
注意:setTimeout()只執行code一次,如果需要多次調用,請使用setInterval()或者讓code自身再次調用setTimeout(),也就是利用遞歸。
setInterval()方法可按照指定的週期來調用函數或計算表達式。它會不停地調用函數,指導clearInterval()被調用或者窗口被關閉。由setInterval()返回的ID值可以用作clearInterval()方法的參數。
語法:setInterval(code,millisec[,"lang"])