---
tags: Javascript,
disqus: hackmd
---
# Javascript的this|chrisHsiao
在看了Huli大神的[淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂](https://blog.huli.tw/2019/02/23/javascript-what-is-this/)後,我覺得很重要的重點。
```
1. 脫離物件的 this 基本上沒有任何意義
2. 沒有意義的 this 會根據嚴格模式以及環境給一個預設值
3. 嚴格模式底下預設就是 undefined,非嚴格模式在瀏覽器底下預設值是 window
4. 可以用 call、apply 與 bind 改變 this 的值
5. 要看 this,就看這個函式「怎麽」被呼叫
6. 可以把 a.b.c.hello() 看成 a.b.c.hello.call(a.b.c),以此類推,就能輕鬆找出 this 的值
```
this的預設值在
1. 嚴格模式底下就都是undefined
2. 非嚴格模式,瀏覽器底下是window
3. 非嚴格模式,node.js 底下是global
## class跟object
基本上,在class跟object裡的this會是自己本身
## 更改 this 的值
[[JS]call、apply、bind](https://hackmd.io/8mTXvpw-R0WJUJAQfSS7Bg?view)
更改 this 的值的方法有三種。
> call、apply、bind
而call跟apply這兩種非常相似
```javascript=
'use strict';
function hello(a, b){
console.log(this, a, b)
}
hello(1, 2) // undefined 1 2
hello.call(undefined, 1, 2) // undefined 1 2
hello.apply(undefined, [1, 2]) // undefined 1 2
```
## class中的 this
## 物件中的 this
```javascript=
const obj = {
value: 1,
hello: function() {
console.log(this.value)
}
}
obj.hello() // 1
```
## 不合群的箭頭函式
自己在寫物件的裡的function的時候就遇過這個問題,沒想到Huli大神也有提到,正好可以解我的疑惑。
> 「在宣告它的地方的 this 是什麼,它的 this 就是什麼」
不是我在講,真的很難懂。
```javascript=
const obj = {
x: 1,
hello: function(){
console.log(this)
const test = () => {
console.log(this.x)
}
test()
}
}
obj.hello();
const hello = obj.hello;
hello();
```
一開始看我也是混亂到不行,但如果回歸到單純一點,就是用call來看,我覺得就清楚很多了
```javascript=
obj.hello.call(obj); //帶了obj進去,所以hello裡的this會是obj這個物件
test.call(); //因為是箭頭函式,所以test的this會是在宣告這個函式時候的當下this,
//也就是hello的this,所以this.x就會印出1
hello.call(); //沒有帶參數進去,所以hello裡的this會是window
test.call(); //因為是箭頭函式,所以test的this會是在宣告這個函式時候的當下this,
//也就是window,而window.x就會是undefined
```
---
如果把test的箭頭函示改回原本的函式又會是怎樣呢?
```javascript=
const obj = {
x: 1,
hello: function() {
console.log('this', this)
function test() {
console.log('this.x', this.x)
}
test.call()
}
}
obj.hello.call();
// const hello = obj.hello;
// hello();
```
把呼叫hello跟test函式的地方加上call來看
```javascript=
obj.hello.call(obj); //帶了obj進去,所以hello裡的this會是obj這個物件
test.call(); //沒有帶參數進去,所以test裡的this會是window
//但是他是 console this.x 所以會看到1
```
再把最下面註解的兩行打開,並把hello也加上call
```javascript=
const hello = obj.hello;
hello.call();
hello.call(); //沒有帶參數進去,所以hello裡的this會是window
test.call(); //沒有帶參數進去,所以test裡的this會是window
//但是他是 console this.x,而window底下沒有x所以是undefined
```
---
### self this
先看看一個範例
```javascript=
var body = document.getElementById('body');
body.addEventListener('click', function() {
console.log("body click's this", this); //id是body的元素
});
console.log('this', this); //window
```
#### 為什麼body click的this返回的不一樣?
簡單的說,因為這時候的this被指定到了body上,所以他返回的就會是id=body的元素。
#### 如何讓body click的時候拿到跟外面一樣的this?
##### 1. 在外層就先指定this
```javascript=
var body = document.getElementById('body');
var test = this;
body.addEventListener('click', function() {
console.log("body click's this", test); //window
});
console.log('this', this); //window
```
這裡就回到標題的self this上,叫self \_this是因為,有人會把`var test = this`的test換成`self`、`_this`、`that`之類的,可以用這幾個關鍵字去搜尋看看。
但我個人是覺得沒差。
[Scope and this in JavaScript](https://www.jackfranklin.co.uk/blog/javascript-variable-scope-this/)
[鐵人賽:JavaScript 的 this 到底是誰?](https://wcc723.github.io/javascript/2017/12/12/javascript-this/)
##### 2. bind()
```javascript=
var body = document.getElementById('body');
body.addEventListener('click', function() {
console.log("body click's this", this); //window
}.bind(this));
console.log('this', this); //window
```
使用函式預設有的bind()這個方法把this帶入。
##### 3. 箭頭函示(arrow function)
```javascript=
var body = document.getElementById('body');
body.addEventListener('click', () => {
console.log("body click's this", this); //window
});
console.log('this', this); //window
```
這就必須提到箭頭函式的特性,他會依據他被建立時的this是什麼,他的this就是什麼。
---
### 參考文章
[淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂](https://blog.huli.tw/2019/02/23/javascript-what-is-this/)
[this 的值到底是什么?一次说清楚](https://zhuanlan.zhihu.com/p/23804247)
[Scope and this in JavaScript](https://www.jackfranklin.co.uk/blog/javascript-variable-scope-this/)
[作用域 (Scope)](https://hackmd.io/zbZx_kfNTQq1jRUA_03QUA?view)
[[JS]call、apply、bind](https://hackmd.io/8mTXvpw-R0WJUJAQfSS7Bg?view)
---
###### tags: `Javascript` `this` `scope`