先判斷程式碼是傳統函式或箭頭函式
this
只與調用方式有關,與怎麼定義 this
無關 。
this
就會指向它,如果 this
前沒有任何物件會指向全域。( 下方會有範例 )setTimeout
為 callback function 是 simple call 的一種形式,在傳統函式寫法下 this
會指向全域,為了避免 setTimeout
的 this
指向全域可使用「 箭頭函式 」或是「 指向其他變數 」。( 最後範例 8 )this
,會看外層函式的 this
指向。
var
、const
、let
) ,this
也會不同,要留意。var a = '全域'
function fn(params) {
console.log(params, this, window, arguments);
debugger;
}
fn(1, 2, 3);
// 執行 debugger ,開發者工具會跳到 Sources 區域 ▲
console.log(params, this, window, arguments);
→ 中為運行函數本身就可以執行的參數內容
params
為外部傳入的參數。
this
目前是指向 windows
,但實際在運作時可能會有很多種不同的指向,此指向會影響在使用框架時指到哪,如果想要指向特定的元件但卻指向錯誤,就會出錯。window
瀏覽器本身就存在的全域變數。arguments
傳統函式會帶入的參數,為類陣列會帶入所有傳入的參數內容。
fn(1, 2, 3);
有三個參數 arguments
會列出所有參數值。var obj = {
name: '小明',
fn: function(params) {
console.log(params, this, window, arguments);
// debugger;
}
}
obj.fn(1 , 2 , 3);
fn:
的函式程式碼與 #1 範例相同,但卻只有 this
有所不同。
{name: "小明", fn: ƒ}
為 this
。傳統函式中的
this
只與調用方式有關,與怎麼定義this
無關 。
大部分情境只須了解其中一種,請看下方 #4 this 的各種運用變化 | this 的判斷方式
//使用 const 與 let 結果會有所不同,所以變數someone 請使用 var 來設定全域變數。
var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
callSomeone(); //這種呼叫方式稱 simple call
// output 全域。
// 如下方所述呼叫函式 callSomeone(); 時前方沒有任何物件,所以指向全域。
this
的判斷 : ( 此判斷方式以傳統函式為主,箭頭函式的判斷法請看 #5 this
陷阱 )
this
就會指向它 ( 例 : #4 );var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
var obj = {
someone: '物件',
callSomeone() {
console.log(this.someone);
}
}
obj.callSomeone();
// output 物件。入上述判斷callSomeone()前方有物件 obj所以指向'物件'
// 呼叫函式時,前面有任何物件 this 就會指向它 ▲
var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
var obj2 = {
someone : '物件2',
callSomeone //ES6 縮寫 ,原始為 callSomeone : callSomeone()
}
obj2.callSOmeone();
//output 物件2
callSomeone
指向 function callSomeone()
。this
就會指向它,所以 this
指向變數 obj2。var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
var wrapObj = {
someone: '外層物件',
callSomeone,
innerObj: {
someone: '內層物件',
callSomeone,
}
}
wrapObj.callSomeone();
wrapObj.innerObj.callSomeone();
callSomeone
皆使用函式 callSomeone()
。this
就會指向它。
wrapObj.callSomeone();
→ 所以 this
指向 wrapObj
,輸出 外層物件
。wrapObj.innerObj.callSomeone();
→ 所以 this
指向 innerObj
,輸出 內層物件
。var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
var obj3 = {
someone: `物件 3`,
fn() {
callSomeone(); //通常不會這樣去取用 this
}
}
obj3.fn();
this
與怎麼定義無關,只和調用方式有關,調用這個 fn()
內的 callSomeone()
函式時前方沒有看到任何物件,就屬於 simple call 會指向全域。
obj3.fn();
→ output 全域this
,結果可能會不如預期,這邊解說範例用。var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
var obj4 = {
someone: '物件 4',
fn() {
//callback function
setTimeout(function () {
console.log(this.someone);
});
}
}
obj4.fn();
this
大多會指向全域,少數會重新定義。this
。MDN - 回呼函式(callback function)
obj4.fn();
→ output 全域var obj = {
data: {
myName: 'hexschool',
},
getName: function () {
console.log(this.data.myName);
}
}
obj.getName();
getName: function ()
為傳統函式,傳統函式的 this 都會看前方呼叫它的是誰。obj.getName();
結果為 hexschool。var obj = {
data: {
myName: 'hexschool',
},
getName: () => {
console.log(this.data.myName);
}
}
obj.getName();
this
。它會看外層函式作用域中的 this
指向,如果外層沒有函式則會指向全域。obj.getName();
結果為 TypeError: Cannot read property 'myName' of undefined
。var myName = '小明';
var obj = {
myName: '小美',
x: function () {
var myName = '小王';
setTimeout(function () {
console.log(this.myName);
}, 0);
},
y: '2',
}
obj.x();
setTimeout(function (){})
為 callback function ( 大部分屬於 simple call 形式 ),會指向全域。obj.getName();
結果為 小明。