JavaScript 之 this 的運作
JavaScript
#JavaScript #Notes 在 JavaScript 中,this 的指向通常是根據函數如何被調用來決定的。
首先我們先觀察一個函式的參數包含哪些東西
一個 function 中包含的參數
var a = '全域';
function fn(params){
console.log(params, this, window, arguments);
debugger;
}
fn(1,2,3);
若開啟 console 可以看到 fn 這個 function 作用域中存在 arguments、params、this、windows 這四個參數
-
arguments 把所有參數傳入,若有三個那就會傳入3個
-
params 預設參數,因只有傳一個所以只有1
-
this 目前是指向window,全域
-
window 為瀏覽器本身存在的全域
this 的指向
重點:this 的指向只跟調用方式有關
simple call
var a = '全域';
function callsomeone(){
console.log(this.someone);
}
callsomeone(); //simple call(簡易呼叫)
因line:5 callsomeone目前沒有任何指向,所以this是指向全域的部分,稱為simple call
物件函式呼叫
Ex.1
var obj = {
someone:'物件',
callsomeone(){
console.log(this.someone);
}
}
obj.someone();
line:7 呼叫函式前若有物件,就會是this的指向,就是obj
Ex.2
var someone = '全域';
function callsomeone(){
console.log(this.someone);
}
var obj2 = {
someone:'物件2',
fn(){
callsomeone();
}
}
obj2.fn();
記得我們 this 的重點是,this 的指向只跟調用方法有關,所以 line:9 的 callsomeone 前沒有任何指向的物件,所以是這裡的 this 會是指向全域,也是 simple call 的一種
物件呼叫函式
function callsomeone(){//3
console.log(this.someone);//4
}
var wrapObj = {
someone:'外層物件',
callsomeone,
innerObj:{//5
someone:'內層物件',//6
callsomeone,//2
}
}
wrapObj.innerObj.callsomeone();//1
this 的指向為 innerObj 物件,結果為內層物件
ES6箭頭函式
重點:箭頭函式沒有自己的 this
Ex.1 傳統函式
var name = '全域';
const person = {
name:'小明',
callName: function(){
console.log('1',this.name);//1小明
setTimeout(function(){
console.log('2',this.name);//2
console.log('3',this);//3
},10);
}
}
person.callName();
line:5 指向 person 物件的 name 小明,setTimeout 大部分屬於 sample call,this 指向全域,line:8 指向 window
Ex.2 箭頭函式
var name = '全域';
const person = {
name:'小明',
callName: function(){
console.log('1',this.name);//1小明
setTimeout(() => { //與外層函式作用域相同
console.log('2',this.name);//2
console.log('3',this);//3
},10);
}
}
person.callName();
箭頭函式 setTimeout 會跟 line:4 外層函式的作用域相同,外層指向哪裡,內層就相同,所以 1:小明、2:小明、3:person物件
Ex.3 箭頭函式
var name = '全域';
const person = {
name: '小明',
callName:() => {
console.log(this.name);
}
}
person.callName();
若外層沒有函式,則指向全域,this 指向全域
實戰手法
實戰中有兩種方式避免 this 不如預期
- this 先指向其他變數
- 使用箭頭函式,相對精簡
this 先指向其他變數
var someone = '全域';
var obj3 = {
someone:'物件3',
fn(){
const vm = this;
setTimeout(function(){ //callback function
console.log(vm.someone);
});
}
}
obj3.fn();
可以確保 this 不受到函式的影響
使用箭頭函式
var someone = '全域';
var obj3 = {
someone:'物件3',
fn(){
setTimeout(() => { //callback function
console.log(this.someone);
});
}
}
obj3.fn();
透過這種方式可以讓內層的作用域與外層相同,this 的指向為全域