1. 普通函數(shù)中
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
console.log('current name is:', this.name);
}
}
obj.fn();//objName
var innerFn = obj.fn;
innerFn();//globalName季惯,瀏覽器和NodeJS不一樣
- 一般情況下最后是誰調(diào)用的函數(shù)(并且此函數(shù)和this直接相關(guān))眠屎,this指向誰
- obj.fn()中音同,調(diào)用fn的是obj對象,所以this指向obj對象料祠,得到的是obj.name
- innerFn()骆捧,沒有調(diào)用方,默認(rèn)為window調(diào)用(瀏覽器中)
1.1 立即執(zhí)行函數(shù)模式
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
function gn() {
console.log('current name is:', this.name);
}
gn();
}
}
obj.fn();//globalName
- 最終【執(zhí)行】的函數(shù)是gn髓绽,而調(diào)用gn的是window(因?yàn)闆]有調(diào)用方)敛苇,此模式類似執(zhí)行回調(diào)函數(shù)
1.2 返回函數(shù)模式
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
return function gn() {
console.log('current name is:', this.name);
}
}
}
obj.fn()();//globalName
2. 構(gòu)造函數(shù)中
var name = "globalName";
function Test(name) {
console.log("current this is: ", this); //Test函數(shù)構(gòu)造的實(shí)例testObj
console.log(this instanceof Test);//true
this.name = name;
}
var testObj = new Test("Lawson");
console.log(testObj.name);//Lawson
- 構(gòu)造函數(shù)中(用new調(diào)用函數(shù)),this指向生成的實(shí)例
var name = "globalName";
function Test(name) {
this.name = name;
return {
name: 'Nion'
};//構(gòu)造函數(shù)中返回了非基本類型
}
var testObj = new Test("Lawson");
console.log(testObj.name);//Nion
var name = "globalName";
function Test(name) {
this.name = name;
return 0;//基本類型
}
var testObj = new Test("Lawson");
console.log(testObj.name);//Lawson
var name = "globalName";
function Test(name) {
this.name = name;
return this;
}
var testObj = new Test("Lawson");
console.log(testObj.name);//Lawson
- 若構(gòu)造函數(shù)中返回了非【基本類型】(number string boolean null undefined symbol bigint)也不是this顺呕,則生成的實(shí)例會被非基本類型替換
3. 結(jié)合call apply bind函數(shù)
- 三者的第一個參數(shù)枫攀,都會改變執(zhí)行函數(shù)中this指向
- call后面接收的參數(shù)括饶,以正常參數(shù)一樣,一個個傳入来涨,最后執(zhí)行函數(shù)
- apply后面接收一個參數(shù)图焰,將所有的正常參數(shù),按照類數(shù)組的方式傳入蹦掐,最后執(zhí)行函數(shù)
- bind的入?yún)⒑蚦all一樣楞泼,但是最后不執(zhí)行函數(shù),而是返回被改變this之后的新函數(shù)笤闯,傳入的參數(shù)會作為新函數(shù)的預(yù)置參數(shù),從而實(shí)現(xiàn)偏函數(shù)的功效
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
console.log('current name is:', this.name);
}
}
//和obj.fn()效果一致棍厂,而且使用call更加不容易混淆this
obj.fn.call(obj);//objName
//和var innerFn = obj.fn; innerFn(); 效果一致
obj.fn.call(window);//globalName
//注意:call后面的參數(shù)颗味,可以傳入null 即obj.fn.call(null)實(shí)現(xiàn)軟綁,但是嚴(yán)格模式下報(bào)錯
4. 箭頭函數(shù)
下面只談和this相關(guān)的內(nèi)容
4.1 立即執(zhí)行函數(shù)模式
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
console.log('this.name of fn is:', this.name);
var arrowFn = () => {
console.log('current name is:', this.name);
}
arrowFn();
}
}
obj.fn();
//current name is: objName
//this.name of fn is: objName
4.2 返回函數(shù)模式
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
console.log('this.name of fn is:', this.name);
return () => {
console.log('current name is:', this.name);
}
}
}
obj.fn()();
//this.name of fn is: objName
//current name is: objName
var arrowFn = obj.fn();
arrowFn();
//this.name of fn is: objName
//current name is: objName
var innerFn = obj.fn;
innerFn()();
//this.name of fn is: globalName
//current name is: globalName
obj.fn().call(window);
//this.name of fn is: objName
//current name is: objName
- 對象中沒有函數(shù)級作用域
var name = 'globalName';
var obj = {
name: 'objName',
methods: {
showName: () =>{
console.log('current name is:', this.name);
}
}
}
obj.methods.showName();//globalName
- JS中說作用域牺弹,一般是按照函數(shù)級作用域進(jìn)行分級的
- 箭頭函數(shù)的this浦马,在聲明的時候已經(jīng)和其父級作用域(函數(shù)級)綁定,無法解綁张漂,bind call apply均不能改變其this指向