前言: 一直都搞不清javascript中this的指向,你不知道的javascript(上卷)這本書中有3章都是在講解this,去年第一次看完還是覺得似懂非懂的,一深入的問還是不清楚,現在在看一遍,真心覺得這本書裡講的是真好,想深入瞭解一下的,這本書是一個不錯的選擇.
下面我就簡單的說一下我的理解,用兩句話記住了javascrpt中this的指向:
this的指向
1, 普通函式指向函式的呼叫者:有個簡便的方法就是看函式前面有沒有點,如果有點,那麼就指向點前面的那個值;
2, 箭頭函式指向函式所在的所用域: 注意理解作用域,只有函式的{}
構成作用域,物件的{}
以及 if(){}
都不構成作用域;
const obj = {
name: 'objName',
say() {
console.log(this.name);
},
read: () => {
console.log(this.name);
}
}
obj.say(); // objName
obj.read(); // undefined
複製程式碼
- 普通函式,呼叫者是obj,所以結果是 objname;也是理解
say()
是普通函式,前面有點,所以this
指向obj
; - 箭頭函式,this指向函式所在的作用域,當前的作用域為全域性環境,所以
this.name
為undefined
, - 舉下面的例子更清楚的瞭解一下箭頭函式this的指向,箭頭函式所在的作用域是普通函式
say
,say()
的呼叫者是obj
const obj = {
say: function () {
setTimeout(() => {
console.log(this)
});
}
}
obj.say(); // obj,此時this指的是定義他的obj
複製程式碼
補充知識點
- 瀏覽器預設的this為window
function test() {
console.log(this);
}
test(); //window
複製程式碼
- node.js中全域性環境預設
this為{}
,普通函式中預設this為global
console.log(this); // {}
function test() {
console.log(this);
}
test(); //global
複製程式碼
來兩道題檢查你是否掌握了
example1
var length = 10;
function fn() {
console.log(this.length);
}
const obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
}
};
obj.method(fn, 1);
複製程式碼
輸出 10, 2
剛開始看到這道題我也是濛濛的,現在也終於理解了,
method這個函式傳入了兩個引數,一個引數為fn()
,fn()
為普通函式,this指向函式的呼叫者,此時指向全域性(也可以看這個函式前面沒有點
),所以執行結果為10,arguments是函式的所有引數,是一個類陣列的物件,arguments[0] (),可以看成是arguments.0(),呼叫這個函式的是arguments
,此時this就是指arguments
,this.length就是angument.length
,就是傳入的引數的總個數2
注:
- 上面例子在node環境中的執行結果為 undefined 2,
var length = 10
改成global.length = 10;
是因為node環境下定義在全域性的變數不會繫結到global,瀏覽器也會自動繫結到全域性環境window - 之前寫的有點小問題,感謝大家的指出:用const來定義length,然後列印0和2; var在全域性定義的變數會自動定義到window,但是const和let在全域性定義的變數不會自動定義到window,改成const列印window.length為0,是因為window.length表示當前頁面有幾個iframe,可以看一下MDN上關於window.length的定義
改成下面這樣結果又是什麼呢?
var length = 10;
function fn() {
console.log(this.length);
}
const obj = {
length: 5,
method: function(fn) {
fn();
const fun = arguments[0];
fun();
}
};
obj.method(fn, 1);
複製程式碼
10, 10
example 2
window.val = 1;
var obj = {
val: 2,
dbl: function() {
this.val *= 2;
val *= 2;
console.log(val);
console.log(this.val);
}
}
obj.dbl(); // 2 4
var func = obj.dbl;
func(); // 8 8
複製程式碼
這個就是有點繞了,不過一步步來分析就很容易理解了:
obj.dbl()
;執行這行程式碼時,this指的是obj
,所以this.val === obj.val*=2
,最後結果為4
,val*=2 === window.val *= 2
,最後結果是2
func()
,執行這行程式碼時,func()
沒有任何字首,this
指的是window.func()
;所以此時this值得是window
,this.val === window.val *= 2
,此時window.val
為4
,val*=2 === window.val *2
,最後結果為8
,最後console.log(this.val)
,與console.log(val)
,指的都是window.val
,最後結果都是8
上述是我自己的理解,如果有什麼問題,歡迎指正~