掌握JavaScript基礎--理解this關鍵字的新思路
阿新 • • 發佈:2018-03-31
handle 無法 公眾號 post tom image gpo alter IT
來自為知筆記(Wiz)
普通函數
下面這種就是普通函數
function add(x, y) {
return x + y;
}
每個普通函數被調用的時候,都相當於有一個this參數傳進來。
內部函數this不會是外部函數傳入的this,相當於和外部的this隔離開了。
function outer() {
function inner() {
console.log(this); // window
}
console.log(this); // ‘outer‘
inner();
}
outer.call(‘outer‘);
相當於:
function outer(_this) { function inner(_this) { console.log(_this); // undefined } console.log(_this); // ‘outer‘ inner(undefined); } outer(‘outer‘);
箭頭函數
const add = (x, y) => {
return x + y;
};
如果你用箭頭函數,內部函數的this和外部是一致的:
function outer() {
const inner = () => {
console.log(this); // ‘outer‘
};
console.log(this); // ‘outer‘
inner();
}
outer.call(‘outer‘);
箭頭函數的this不會被call方法影響,它總是和箭頭函數所在的位置有關:
它所在的位置(也就是作用域)的this指向誰,箭頭函數裏面的this就指向誰。
function ordinary() {
const arrow = () => this;
console.log(arrow.call(‘goodbye‘)); // ‘hello‘
}
ordinary.call(‘hello‘);
普通函數作為方法
如果一個函數賦值給了屬性,就變成了方法:
const obj = {
prop: function () {}
};
調用方法的方式是:
obj.prop(x, y)
相當於:
obj.prop.call(obj, x, y)
陷阱
1 回調函數裏面用this
回調裏面執行(A),你發現logStatus訪問不了。這個是因為this被阻隔了。
performCleanup() {
cleanupAsync()
.then(function () {
this.logStatus(‘Done‘); // (A)
});
}
你應該采用箭頭函數:
performCleanup() {
cleanupAsync()
.then(() => {
this.logStatus(‘Done‘);
});
}
2 map方法裏面用this
同理,this也是訪問不了company和name的
prefixNames(names) {
return names.map(function (name) {
return this.company + ‘: ‘ + name; // (A)
});
}
采用箭頭函數:
// Inside a class or an object literal:
prefixNames(names) {
return names.map(
name => this.company + ‘: ‘ + name);
}
3 用函數作為回調
class UiComponent {
constructor(name) {
this.name = name;
const button = document.getElementById(‘myButton‘);
button.addEventListener(‘click‘, this.handleClick); // (A)
}
handleClick() {
console.log(‘Clicked ‘+this.name); // (B)
}
}
改為:
class UiComponent {
constructor(name) {
this.name = name;
const button = document.getElementById(‘myButton‘);
button.addEventListener(
‘click‘, this.handleClick.bind(this)); // (A)
}
handleClick() {
console.log(‘Clicked ‘+this.name);
}
}
bind函數能讓普通的函數調用無法修改this:
function returnThis() {
return this;
}
const bound = returnThis.bind(‘hello‘);
bound(); // ‘hello‘
bound.call(undefined); // ‘hello‘
保持正確的做法
1 用ESlint的rules: no-invalid-this
避免普通函數內部有this,一般在方法內使用this或者箭頭函數內使用
2 不要把this當做參數
因為這樣你就不能用箭頭函數了
beforeEach(function () {
this.addMatchers({ // access API object
toBeInRange: function (start, end) {
···
}
});
});
可以很容易被改寫:
beforeEach(api => {
api.addMatchers({
toBeInRange(start, end) {
···
}
});
});
原文鏈接:http://2ality.com/2017/12/alternate-this.html
作者知乎/公眾號:前端瘋 (一群熱愛前端的一線程序員維護,想要用前端改變世界。)
來自為知筆記(Wiz)
掌握JavaScript基礎--理解this關鍵字的新思路