[TOC]
理解 `this` 的第一步就是要明白:
`this`既不指向函數(shù)自身,也不指向函數(shù)的詞法作用域;
`this`是在運行時進行綁定的,而不是在編寫時綁定,它的上下文取決于函數(shù)調(diào)用時的各種條件;
`this`的綁定和函數(shù)聲明的位置沒有任何關(guān)系,只取決于函數(shù)的調(diào)用位置和調(diào)用方式;
`this`綁定規(guī)則有4點:按優(yōu)先級1到4判斷
1. 由`new`調(diào)用?綁定到新創(chuàng)建的空對象;
2. 由`call、apply、bind`調(diào)用?綁定到指定的參數(shù)對象;如`foo.call(obj)`
3. 由上下文對象調(diào)用?綁定到這個上下文對象;如`obj.foo()`
4. 默認(rèn)情況下綁定到全局對象( `window` ),在嚴(yán)格模式下綁定到`undefined`;
# 一般情況
1. 情況1:如果一個函數(shù)中有 `this` ,但是它沒有被上一級的對象所調(diào)用,那么 `this` 指向的就是 `window`,這里需要說明的是在 js 的嚴(yán)格模式 中 `this` 指向的不是 `window`,但是我們這里不探討嚴(yán)格問題(默認(rèn)的`this`不再是`window`,而是 `undefined`。),你想了解可以自行上網(wǎng)查找。
2. 情況2:如果一個函數(shù)中有`this`,這個函數(shù)有被上一級的對象所調(diào)用,那么`this`指向的就是上一級的對象。
3. 情況3:如果一個函數(shù)中有`this`,**這個函數(shù)中包含多個對象,盡管這個函數(shù)是被最外層的對象所調(diào)用,`this`指向的也只是它上一級的對象**
例子3可以證明,如果不相信,那么接下來我們繼續(xù)看幾個例子。
```js
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //undefined
console.log(this); //window
}
}
}
var j = o.b.fn;
j(); // 這里在運行時是 window 環(huán)境下調(diào)用了 fn
```
# 改變this的指向請看[Javascript中apply、call、bind](Javascript中apply、call、bind.md)
解JS構(gòu)造函數(shù)中 `this` 和 `return`:
先看一段代碼,
```
function Foo(name,age){
this.name=name;
this.age=age;
}
var foo=new Foo("Tom",14);
foo.name; //Tom
foo.age; //14
```
使用構(gòu)造函數(shù)實例化發(fā)生的流程:
1. 建立一個`foo`的空對象。
2. 將構(gòu)造函數(shù)中的`Foo`的`this`指向?qū)ο骮foo`。
3. `foo`的`__proto__`屬性指向`Foo`函數(shù)的`prototype`原型。
4. 執(zhí)行構(gòu)造函數(shù)中的代碼。
相對于普通函數(shù),構(gòu)造函數(shù)中的 `this` 是指向?qū)嵗?,而普通函?shù)調(diào)用中的`this` 是指向`windows`的。
構(gòu)造函數(shù)中如果加入了 `return` 的話,分兩種情況
```
function Foo(name,age){
this.name=name;
this.age=age;
return {name:"Jeff"}
}
var foo=new Foo("Tom",14);
foo.name; //Jeff
```
1. return 的是五種簡單數(shù)據(jù)類型:`String,Number,Boolean,Null,Undefined`。
這種情況下,忽視`return`值,依然返回this對象。
2. return 的是`Object`。
```js
function fn()
{
this.user = '追夢子';
return {};
}
var a = new fn;
console.log(a.user); //undefined
```
```js
function fn()
{
this.user = '追夢子';
return function(){};
}
var a = new fn;
console.log(a.user); //undefined
```
?這種情況下,不再返回 `this` 對象,而是返回 `return` 語句的返回值。
# 箭頭函數(shù)中的 this
箭頭函數(shù)中的 this:
* ?ES6 中箭頭函數(shù)( `=>`) 內(nèi)部沒有 `this` 對象,導(dǎo)致 **內(nèi)部的 `this`就是上一層作用域的 `this`**;默認(rèn)指向在定義它時所處的對象(宿主對象),另外由于沒有 `this`,所以它不能用于定義構(gòu)造函數(shù)。
* ?而不是執(zhí)行時的對象,定義它的時候,可能環(huán)境是 `window`,也有可能是其他的。
由于箭頭函數(shù)不綁定 `this`, 它會捕獲其所在(即定義的位置)上下文的 `this` 值, 作為自己的 `this` 值,
1. `this`一旦綁定了上下文,就不會被任何代碼改變。 所以 `call() / apply() / bind()` 方法對于箭頭函數(shù)來說只是傳入?yún)?shù),對它的 `this` 毫無影響。
2. 考慮到 `this` 是詞法層面上的,嚴(yán)格模式中與 `this` 相關(guān)的規(guī)則都將被忽略。(可以忽略是否在嚴(yán)格模式下的影響)
```js
const adder = {
base : 1,
add : function(a) {
var f = v => v + this.base
return f(a);
},
addThruCall: function inFun(a) {
var f = v => v + this.base;
var b = { base : 2 };
return f.call(b, a);
}
};
console.log(adder.add(1)); // 輸出 2
console.log(adder.addThruCall(1)); // 仍然輸出 2(而不是3,其內(nèi)部的this并沒有因為call() 而改變,其this值仍然為函數(shù)inFun的this值,指向?qū)ο骯dder
```
## 箭頭函數(shù)當(dāng)做一個方法使用
```js
function test (){
this.a = 'a1';
this.c = {
a: 'a2',
run: function (){
console.log(this.a) // 這層的作用域按照上述規(guī)則
return ()=> {
console.log(this.a) // 綁定了上層作用域
}
}
}
}
const t = new test()
t.c.run()() // 'a2' 'a2'
// const f = t.c.run
// f()(); // 'undefined' 'undefined'
```
上例子中,箭頭函數(shù)中的 `this` 綁定了上層作用域的`this`,只會受到上層作用域的影響!這里的它的上層作用域會受到
# 參考
[徹底理解js中this的指向,不必硬背。](https://www.cnblogs.com/pssp/p/5216085.html)
[meaning-of-this-in-node-js-modules-and-functions](https://stackoverflow.com/questions/22770299/meaning-of-this-in-node-js-modules-and-functions)
- 步入JavaScript的世界
- 二進制運算
- JavaScript 的版本是怎么回事?
- JavaScript和DOM的產(chǎn)生與發(fā)展
- DOM事件處理
- js的并行加載與順序執(zhí)行
- 正則表達(dá)式
- 當(dāng)遇上this時
- Javascript中apply、call、bind
- JavaScript的編譯過程與運行機制
- 執(zhí)行上下文(Execution Context)
- javascript 作用域
- 分組中的函數(shù)表達(dá)式
- JS之constructor屬性
- Javascript 按位取反運算符 (~)
- EvenLoop 事件循環(huán)
- 異步編程
- JavaScript的九個思維導(dǎo)圖
- JavaScript奇淫技巧
- JavaScript:shim和polyfill
- ===值得關(guān)注的庫===
- ==文章==
- JavaScript框架
- Angular 1.x
- 啟動引導(dǎo)過程
- $scope作用域
- $q與promise
- ngRoute 和 ui-router
- 雙向數(shù)據(jù)綁定
- 規(guī)范和性能優(yōu)化
- 自定義指令
- Angular 事件
- lodash
- Test
