初衷:
這篇關於this
的文章,僅僅是自己認為比較重要且易混淆的知識點。
內容
1.含義:
在JavaScript
中,this
物件是指當前函式中正在執行的上下文環境,因此this
並非是定義時(箭頭函式除外)。
2.this
指向:
永遠指向最後呼叫它的物件。 簡單記憶:A.B()
這裡的this
就指.
左邊的A
.
3.this
物件分類:
this
物件分類:- 全域性物件
- 當前物件
- 任意物件
判斷處於哪種this物件,這個取決於函式的呼叫方式。而JavaScript中的函式呼叫方式又分為四種:
JavaScript
中的函式呼叫方式:- 函式呼叫
- 作為物件的方法呼叫
- 建構函式呼叫
call 、apply 、bind
4. 具體內容:
4.1 函式呼叫
var a = 11;
function foo() {
var a = 22;
console.log(this.a);//11
}
foo();
console.log(this.a);//11
複製程式碼
函式呼叫:在獨立呼叫中,this
在非嚴格模式下指向全域性物件window
.在嚴格模式下this
是 undefined
。在這裡,用var
宣告一個變數和給this
以及window
新增屬性是等價的。
var myname = "princess";
console.log(this.myname); //princess
console.log(window.myname); //princess
複製程式碼
接著可能會有下面的疑惑:
var foo = 123;//foo 是變數
window.bar = 345;//bar 是屬性
delete foo;
delete bar;
console.log(this.foo,this.bar);//123,undefined 為什麼不一樣呢?
複製程式碼
delelte刪除不了變數、刪除不了原型鏈中的變數、可以刪掉物件屬性!
還得注意以下一點:
被(…)();
這樣形式(IIFE(立即呼叫的函式表示式))
封裝的函式會立即被呼叫,也就是說等同於被獨立呼叫,因此它內部的this
是全域性變數,所以輸出的是全域性變數。
4.2 作為物件的方法呼叫
var b = 33;
var o = {
b: 44,
f: function() {
return this.b;
}
};
console.log(o.f());//44
複製程式碼
作為物件的方法呼叫:this
指向該物件(這裡即物件o
)。
但是當物件的方法被賦予給一個變數時,其相當於函式觸發,此時的this為 window (非嚴格模式下)或者 undefined(嚴格模式下)。
var b = 33;
var o = {
b: 44,
f: function() {
return this.b;
}
};
console.log(o.f());//44
var c = o.f; // this == window || undefined
c();//33
複製程式碼
4.3 建構函式呼叫
new
方法建立物件的時候,會經過如下過程:- 建立物件,將
this
值賦予新的物件; - 呼叫建構函式,為
this
新增屬性和方法; - 返回
this
給當前的物件.
- 建立物件,將
注意關鍵字 new
function Person(name, age) {
this.name = name;
this.age = age;
return {
name: 'Mary'
};
}
var person1 = new Person('Jack');
console.log(person1.name); // 'Mary'
console.log(person1.age); // undefined
複製程式碼
而下面的情況:
function Person(name, age) {
this.name = name;
this.age = age;
return this;
}
var person1 = Person('Bob', 18);
console.log(person1.name); // Bob
console.log(window.name); // Bob
console.log(person1 === window); // true
複製程式碼
建構函式呼叫:this
指向該例項物件。
4.4 call 、apply 、bind
call
和apply
均可以改變this
指向,差別在於傳入引數的不同。
A.call(this,arg1,arg2...,argn)
A.apply(this,[arg1,arg2...,argn])
如果第一個引數為null
或者undefined
,那麼就非嚴格模式下預設為此時的this
為window
物件,嚴格模式下為undefined
.而bind
函式返回的是一個新的函式,即方法,不是立即執行函式,需要手動去呼叫bind()
.
使用 bind()方法建立的上下文,其為永久的上下文環境,不可修改,即使是使用 call 或者 apply方法,也無法修改 this 所指向的值。
5. 還有一種情況:
箭頭函式:此時會從包裹它的函式或作用域中獲取this
的值。
箭頭函式中的this
在定義它的時候已經決定了,與如何呼叫以及在哪裡呼叫它無關,包括 (call, apply, bind)
等操作都無法改變它的this
。
var x=11;
var obj={
x:22,
y:this,
say:()=>{
console.log(this.x);
}
}
obj.say();//11
console.log(obj.y);//window
複製程式碼
這裡按照上述“定義”時決定this
指向,應該輸出22
,但是又可以看出obj
物件中的this
指代的是window
,也就是全域性環境,故箭頭函式中的this
就會就近找到上一個物件中this
所指代的物件。obj
內部屬性y
就為obj
內部this
指代的物件,輸出是window
.
關於這點,解釋的還不是太清楚,再補充!
結語
溫故而知新。