## Es6之關于`this` (上)
資料來源:
? - MDN
? - 你不知道的js上卷
? - [馮羽](https://github.com/mqyqingfeng/Blog/issues/3)
### 前言介紹
`this`關鍵字是JavaScript中最復雜的機制之一,它是一個特別的關鍵字,被自動定義在所有函數的作用域中。但是即使是非常有經驗的JavaScript開發者也很難說清他到底指向什么
——Arthur C. Clarke
全局環境下任何在函數體外部的`this`都指向全局對象
```javascript
// 在瀏覽器中, window 對象同時也是全局對象:
console.log(this === window); // true
a = 37;
console.log(window.a); // 37
this.b = "MDN";
console.log(window.b) // "MDN"
console.log(b) // "MDN"
```
### 對This的誤解
我們很容易把`this`理解為指向函數自身,從`this`的字面意思可以這么理解
實際上是這樣的嗎我們可以看一下MDN上的例子
```javascript
// 將一個對象作為call和apply的第一個參數,this會被綁定到這個對象。
var obj = {a: 'Custom'};
// 這個屬性是在global對象定義的。
var a = 'Global';
function whatsThis(arg) {
return this.a; // this的值取決于函數的調用方式
}
whatsThis(); // 'Global'
whatsThis.call(obj); // 'Custom'
whatsThis.apply(obj); // 'Custom'
```
我們把它復制到瀏覽器中測試一下是否如此。結果是當然的
可以看出this的值是取決于函數調用的方式這是不是非常有趣
我們再來看一個例子//來自你不知道的JavaScript上卷
```javascript
function foo(num){
console.log('foo :' + num)
this.conut++ //記錄被調用次數
}
foo.count = 0;
var i;
for (i=0; i<10; i++){
if(i > 5){
foo(i);
}
}
console.log(foo.count)//foo被調用了多少次呢?
```
打印后發現這并不是我們想要的值,雖然屬性名相同但是它打印的并不是函數里頭的`conut`所以打印出來是0??
**一般人會這樣解決請看下面**
```javascript
//聲明
var data ={
count: 0
}
```
這樣的確能把調用次數打印出來,涉及詞法作用域
```
作用域是指程序源代碼中定義變量的區域。
作用域規定了如何查找變量,也就是確定當前執行代碼對變量的訪問權限。
JavaScript采用詞法作用域(lexical scoping),也就是靜態作用域。
```
## 靜態作用域與動態作用域
因為JavaScript采用的是詞法作用域,函數的作用域在函數定義的時候就決定了。
而與詞法作用域相對的是動態作用域,函數的作用域是在函數調用的時候才決定的。
讓我們認真看個例子就能明白之間的區別:
```
var value = 1 ;
function foo(){
console。log(value);
}
function bar(){
var value = 2 ;
foo();
}
bar();
//結果是???
```
假設JavaScript的采用靜態作用域,讓我們分析下執行過程:
執行FOO函數,先從FOO函數內部查找是否有局部變量值,如果沒有,就根據書寫的位置,查找上面一層的代碼,也就是值等于1,所以結果會打印1。
假設的JavaScript采用動態作用域,讓我們分析下執行過程:
執行FOO函數,依然是從富函數內部查找是否有局部變量值。如果沒有,就從調用函數的作用域,也就是桿函數內部查找值變量,所以結果會打印2。
前面我們已經說了,JavaScript采用的是靜態作用域,所以這個例子的結果是1。
## 動態作用域
也許你會好奇什么語言是動態作用域?
bash就是動態作用域,不信的話,把下面的腳本存成例如scope.bash,然后進入相應的目錄,用命令行執行`bash ./scope.bash`,看看打印的值是多少。
```
value = 1
function foo(){
echo $ value ;
}
function bar(){
local value = 2 ;
foo ;
}
酒吧
```
**This**及不指向函數自身也不指向函數的語法作用域
**This** 實際上是在函數被調用時發生的綁定,他指向什么完全取決于函數在哪里調用。
## Call
一句話介紹 call:
> call() 方法在使用一個指定的 this 值和若干個指定的參數值的前提下調用某個函數或方法。
>
> apply 的實現跟 call 類似
舉個例子:
```
var foo = {
value: 1
};
function bar() {
console.log(this.value);
}
bar.call(foo); // 1
```
注意兩點:
1. call 改變了 this 的指向,指向到 foo
2. bar 函數執行了
- 前言
- 你真的懂This嗎?
- 對象和對象構造函數
- 工廠功能和模塊模式
- API的使用
- async and await
- 關于async的很棒的一篇文章
- 掘金:關于forEach,map,fiter循環操作
- Node.js 實例與基礎
- 原創: Express 學習使用筆記
- 零碎知識點方法
- 關于滾動吸頂的方法
- Vue學習筆記
- Vue向導
- vuex是啥?
- vue代碼風格指南
- 關于vue的初體驗
- 超詳細解毒Vue
- Vue實例
- 模版語言
- 組件基礎
- 條件渲染、列表渲染、Class與style綁定
- Todolist的制作超詳細
- vue-router
- Vue基礎2.0x 筆記
- 搭建vuepress
- JavaScript之ES6
- 箭頭函數
- 這就是This