關於JavaScript中的this指向總結

來源:關於JavaScript中的this指向總結

關於JS中this指向問題,簡單地說就是:哪個對象調用了函數,函數中的this就指向這個對象。按以下幾種情況進行討論:

1. 普通函數調用

var num = 10
function fun1(){
    console.log(this) /* Window */
    console.log(num) /* 10 */
}
fun1()
/* 
相當於: window.fun1()
*/

這種情況下,我們直接使用fun1()調用函數,其實就是window.fun1(),所以this就是指向的是調用函數的對象——window對象。

2. 對象函數調用

var num = 10
var obj={
    a:12,
    fn:function(){
        cons.log(this) /* {a: 12, fn: f} */
        console.log(this.a)  /* 12 */
        console.log(this.num) /* undefined */
    }
}
obj.fn()

可以看到調用fn函數的是obj對象,所以this指向的是obj對象,obj對象中沒有num,所以打印出來是undefined。

3. 構造函數調用

function Person(name,age){
	this.name = name
	this.age = age
}
var p = new Person('tanjia','18')
/*
	上一步相當於:
	p.name = 'tanjia'
	p.age = '18'
*/
console.log(p) /* Person {name: "tanjia", age: "18"} */

構造函數就是用new 操作符去調用一個函數,這個構造函數內部的this指向新的實例,如:

var p = new Person('tanjia','18')

過程中this指向p。

關於new操作符創建對象時發生的事情:  

第一步: 創建一個Object對象實例

第二步: 將構造函數的執行對象賦給新生成的這個實例

第三步: 執行構造函數中的代碼

第四步: 返回新生成的對象實例

4. apply、call、bind調用

apply,call,bind都是來改變this的指向,它們的第一個參數是this指向的那個對象,但是apply接受的第二個參數是數組,call和bind接受的參數是一系列單獨的變量。
apply與call立即執行
bind返回一個函數,如果要執行需要再調用

例如:

var obj = {
	a:1,
	b:2,
	add(name) {
		console.log(this.a + this.b)
		console.log(name)
	}
}

var a = {
	a:2,
	b:2,
}
var b = {
	a:4,
	b:2,
}
var c = {
	a:5,
	b:6,
}
/* this指向a對象,2+2=4 */
obj.add.call(a,"call") /* 4 call */

/* this指向b對象,4+2=6 */
obj.add.apply(b,["apply"]) /* 6 apply */

/* this指向c對象,5+6=4 */
obj.add.bind(c,"bind")() /* 11 bind */

從上面的代碼中可以看出,我們利用call、apply、bind來改變this指針的指向,傳入的第一個參數即是this的指向。

5. 箭頭函數調用

箭頭函數沒有this, 它的this是繼承而來,默認指向在定義它時所處的對象(宿主對象), 而不是執行時的對象。

var obj = {
	a:10,
	b:function(){
		console.log(this) /* {a: 10, b: ƒ} */
		setTimeout(function(){
			console.log(this) /* Window */
			console.log(this.a) /* undefined */
		})
	}
}
obj.b()

通過上面代碼可以看到,函數obj.b()中的this指向的是obj這個對象,而在setTimeout中函數是普通函數,它的this指向的是window對象。

現在,我們將setTimeout中的函數改爲箭頭函數,上述中我們知道箭頭函數沒有this,this是繼承而來。

var obj = {
	a:10,
	b:function(){
		console.log(this) /* {a: 10, b: ƒ} */
		setTimeout(()=>{
			console.log(this) /* {a: 10, b: ƒ} */
			console.log(this.a) /* 10 */
		})
	}
}
obj.b()

可以看到,箭頭函數中的this指向了obj對象(繼承了外部的this),可以訪問對象中的元素。

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