# this
###### tags: `Js` `核心Js`
[直接看這篇](https://ithelp.ithome.com.tw/articles/10193193)
* this 代表的是 function **執行時所屬的物件**,而不是 function 本身。
* 每個執行環境都有屬於自己的this關鍵字(自然產生)
* this與函式如何宣告**沒有關聯性**,僅與呼叫方法有關
* **嚴格模式**下,簡易呼叫會有很大的改變

> 百分之95的this指向都是以上(如果前面有物件就指向物件,沒有就指向全域
#### 影響函式 [this](https://blog.techbridge.cc/2019/02/23/javascript-this/) 的調用方式
* 作為物件方法(最常運用 this 的方法)
* 簡易呼叫(絕大多數的呼叫方式)
* bind, apply, call 方法
* new
* DOM 事件處理器
* 箭頭函式(ES6)

(圖片來源:六角學院)
> 例
```javascript=
function callName(){
console.log(this, this.myName);
}
var family = {
myName: '小明家',
callName: callName,
Ming: {
myName: '小明',
callName: callName
}
}
family.callName();
family.Ming.callName()
```
回傳:

### this 的 [call, apply, bind](https://ithelp.ithome.com.tw/articles/10195896)
call、apply、bind 三者都是 JavaScript Function 的內建函式,他們與 this 的關係重大,除此之外,call & apply 可以作為呼叫 Function 的另一個手段,而 bind 則會回傳一個經過包裹後的 Function 回來。
#### call (立刻執行)
* 第一個參數:
輸入的物件會被指定為目標函式中的 this
* 第二以後的參數:
會作為參數傳進目標函式中,如果目標函式中不需要參數則不要傳入即可
#### apply (立刻執行)
* 第一個參數:
輸入的物件會被指定為目標函式中的 this
* 第二個參數:
必須是**陣列**,會把陣列中的每個元素作為參數傳進目標函式中,如果目標函式中不需要參數則不要傳入即可
#### bind (非立刻執行)
* 明確指定 this
* 回傳一個包裹函式,當我們執行這個函式時,同時也會將帶入 bind 的 arguments 一起帶進 Function 中。類似 [Currying](https://jigsawye.gitbooks.io/mostly-adequate-guide/content/ch4.html) 的概念。
全域

> 例 (call,apply)
```javascript=
function fn(this,part1,part2) {
console.log(this,part1,part2);
}
fn.call(family,1,2);
fn.apply(family,[3,4]);
```
因為this會呼叫全域(window)所以會輸出myName:"小明家"

> 例 (bind)
函式表達式需先呼叫(fn2();)才能執行
```javascript=
var fn2 = fn.bind(family, '小明', '小華');
fn2(); //且不能加入參數
```
### 進階
第1筆雖傳入數字與字串但this是物件所以會轉換成物件
```javascript=
fn.call(1, '小明', '小華');
fn.call('文字', '小明', '小華');
fn.call(undefined, '小明', '小華');
```
第三行遵循[嚴格模式](https://www.casper.tw/javascript/2017/12/15/javascript-use-strict/)

### 嚴格模式
* 加入'use strict'即可運作
* 並不會影響不支援嚴格模式的瀏覽器
* 可依據執行環境設定'use strict'
* 透過拋出錯誤的方式消除一些安靜的錯誤(防止小錯誤)
* 禁止使用一些有可能被末來版本 ECMAScript 定義的語法

例1 (嚴格模式下不能直接對變數宣告)
```javascript=
(function() {
'use strict'; //執行嚴格模式
a = '小明';
}) ():
```

例2
```javascript=
function callStrict(part1, part2) {
'use strict';
console.log(this, typeof this, part1, part2);
}
callStrict.call(1, '小明', '小華'); //維持數字1不會變成建構式
callStrict.call(undefined, '小明', '小華'); //維持undefined不會變成建構式
callStrict('小明', '小華');//簡易呼叫會輸出上次抓到的值
```

> 補充
DOM:
```htmlmixed=
<button onclick="console.log(this)">這是一個按鈕</button>
//log改成dir可以輸出button
```
