作為一個js菜雞的我而言,在之前講到過那麼多的js鍊式查找機制,比如說原型鍊,作用域鍊等等,想當然的把這個機制帶入到了this指向上邊,結果就是這個this指向指的我萬臉懵逼(标題換字了,擔心被河蟹),在經過漫長的通(gou)俗(pi)易(bu)懂(tong)的 ECMAScript規範閱讀之後,分享一下我所認知的this指向
簡而言之,js中this的指向不是在函數定義的時候确定的,而是在調用的時候建立階段确定的,也就是說this指向誰,完全取決于函數的調用方式
常見的幾種調用方式
- 直接調用, 比如說
function a() { console.log(this); } a();
這個例子裡邊this指向的是全局對象,在用戶端的全局對象是window對象,在node 中的全局對象是global對象
(function a() {
function b() {
console.log(this);
}
b()
})()
直接調用指的是直接用函數名稱後邊加()執行調用的函數,無論是否在全局作用域
- 間接調用
const obj ={ name:'obj對象', a(){ console.log(this) } } obj.a()
如圖
在圖中我們可以看到我們在對象裡邊調用對象裡邊的方法的時候,this指向的是obj對象,
或者說外邊有一個函數 然後給一個obj對象的屬性指派
const obj ={
name:'obj對象',
a(){
console.log(this)
}
}
obj.a()
obj.b=function(){
console.log(this,'b')
}
obj.b()
列印的結果都是obj對象
- new調用
當我們他用過new 建立一個新的對象的時候,new會調用這個構造函數來建立一個對象,那麼這個對象裡邊的this是這個被new的函數調用的,那麼自然 new調用的時候,this就是指向這個新對象的
function A(data) {
this.data = data;
}
class B{
constructor(data){
this.data = data
}
}
let a = new A("A");
let b = new B("B");
console.log(a.data);
console.log(b.data);
如圖
這個new,在建立對象的時候做了什麼,我們會在下一篇部落格裡邊仔細說明
- 箭頭函數中的this
箭頭函數可以了解成是是一個文法糖,他沒有自己的this綁定,箭頭函數中使用的this是包含他的那個函數的this
比如說
const obj = {
a() {
return () => {
console.log(this);
};
}
}
上邊這段代碼被轉譯成es5 的時候如下
const obj = {
a: function a() {
var _this = this;
return function () {
console.log(_this);
};
}
};
綜合以上所有的代碼,得出一個結論就是,在js中this的綁定正常來講是指向調用這個方法的對象來确定的,當然還有一些不正常的方法,可以改變this的指向
注意 ,下邊介紹的幾種方法,不能改變箭頭函數的this指向,箭頭函數本身是沒有this綁定的,在介紹完不正常的情況後,再來說一說那些能夠改變this指向的方法
ECMAScript 5.1 規範的this指向
js中this的綁定正常來講是指向調用這個方法的對象來确定的
這句話在理論上是這麼講,在工作中正常的調用的話,這個理論是沒有毛病的,在 ECMAScript 5.1 的規範裡邊規定,在js裡邊分為語言類型和規範類型
- 語言類型
ECMAScript 裡邊的語言類型規定的是我們可以直接操作的一些類型,比如string number,object等等這些
- 規範類型
規範類型ECMAScript 裡邊指的是一種抽象的規範,他們并不是讓我們用來進行操作的,二是用來描述一些行為或者邏輯的,比如說typeof delete等等
ECMAScript 5.1 裡邊的this規定大概講就是這樣的,每個對象裡邊有一個Reference 規範類型,this會根據Reference這個規範類型進行指派
ECMAScript 5.1
規範奉上 Reference 這個東西大家簡單的了解成是()前邊的那一塊就好了,上邊我們講的那些正常的就是說左邊是
- 函數定義表達式
- 屬性通路表達式
- 對象建立表達式
- 屬性建立表達式
這幾種情況,在這幾種情況的時候上邊那句話是成立的
但是如果不是這上邊的那幾句話的時候,比如說括号裡邊是一個和函數相關計算或者一個運算符等等
這個時候this會指向undefined ,這個時候在非嚴格模式的情況下會被隐式轉換成window對象
var value = 1;
var obj = {
value: 2,
a() {
return this.value;
}
}
console.log(obj.a());
console.log((obj.a)());
console.log((obj.a = obj.a)());
console.log((false || obj.a)());
console.log((obj.a, obj.a)());
記得之前看到過這個一個例子,運作結果如圖
時間關系就說這些,下一篇部落格會說new在運作時候過程和改變this指向的