JavaScript 中 this 指向問題終結篇

前言

Javascript 中的 this 關鍵字總是指向一個對象,這個對象是根據函數運行時的環境而定的,總結下來也不外乎以下六種情況。

一、在JS代碼的最外層

在JS代碼的最外層,this指向window對象

var name = "光頭纔是最強";
			
console.log(this);
console.log(this.name);

效果圖

二、作爲對象的方法調用

當函數是作爲對象的屬性調用時,this指向這個對象

var name = '什麼是最強';
var obj = {
	name: '光頭纔是最強',
	getName: function() {
		console.log(this.name);
	}
}

obj.getName();

效果圖

三、作爲普通函數調用

當函數是作爲普通函數調用時,this指向window

var name = '什麼是最強';
var getName = function() {
	var name = '光頭纔是最強';
	console.log(this);
	console.log(this.name);
}

getName();
console.log(this);
console.log(this.name);

效果圖

四、構造器調用

當函數被當作構造器來創建對象時,函數中的this指向創建出來的對象

var name = "什麼是最強"
var myClass = function() {
	this.name = "光頭纔是最強";
};
var classA = new myClass();

console.log(classA.name);

效果圖
當函數作爲構造器被調用時,有一種情況要注意,就是如果函數返回了一個對象,那麼this的指向就會指向這個被返回的對象,而不是用構造器 new 出來的對象

var name = "什麼是最強"
var myClass = function() {
	this.name = "光頭纔是最強";
	return {
		name: "沒想到吧"
	}
};
var classA = new myClass();

console.log(classA.name); //函數返回一個對象,this會指向這個被返回的對象

效果圖

五、Function.prototype.call 或 Function.prototype.apply 調用

有用過 call 和 apply 的同學都知道這兩個方法可以改變函數的this指向(沒了解過或不熟練的同學一定要認真學)

var name = "什麼是最強"
var obj1 = {
	name: "熊大"
}
var obj2 = {
	name: "光頭纔是最強",
	getName: function() {
		return this.name;
	}
};

console.log(obj2.getName.call(obj1)); //用call將原本指向obj2的this,改成指向obj1

效果圖

六、箭頭函數中的this

在ES6中允許使用 => 來定義函數,這種函數叫做箭頭函數,他本身沒有this,他的this是從定義時環境的this引用而來的

var name = '沒想到吧';
var obj = {
	name: "光頭纔是最強",
	getNameSimple: function() {
		return this.name;
	},
	getNameArrow: () => {
		return this.name;
	}
}

console.log(obj.getNameSimple()); //普通函數 getNameSimple 作爲對象屬性調用,this指向對象
console.log(obj.getNameArrow()); //箭頭函數 getNameArrow 的this引用定義時環境的this,
								//getNameArrow定義時環境的this是window

效果圖
普通函數的this是可以動態改變的,而箭頭函數的this是固定的,在定義時引用環境中的this後將無法改變

var name = '光頭纔是最強';
var myClass = function() {
	this.name = "沒想到吧";
	this.arrowFn = () => {
		console.log(this.name);
	};
};

var classA = new myClass();
var fn = classA.arrowFn;
fn(); //用普通函數調用的方式調用arrowFn,理論上此時this應該指向window,但由打印結果
      //可知this是指向了arrowFn定義時的this,說明箭頭函數的this確實不會改變

效果圖
由於箭頭函數的this是固定不變的,所以在箭頭函數上使用call、apply方法將無法改變this指向

var name = "沒想到吧";
var obj1 = {
	name: "光頭纔是最強"
}
var obj2 = {
	name: "什麼是最強",
	getNameSimple: function() {
		return this.name;
	},
	getNameArrow: () => {
		return this.name;
	}
}
			
console.log(obj2.getNameSimple());	        //普通函數作爲對象屬性調用,this指向對象
console.log(obj2.getNameSimple.call(obj1));	//普通函數this指向可變,用call改變普通函數this指向有效
console.log(obj2.getNameArrow());           //箭頭函數定義時環境中的this指向window,所以箭頭函數this指向window
console.log(obj2.getNameArrow.call(obj1));  //箭頭函數this指向不可變,用call改變箭頭函數this指向無效

效果圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章