---
# System prepended metadata

title: JS 核心觀念
tags: [Note]

---

---
tags: Note
---

# JS 核心觀念

## Javascript 
### 基本型別
- primitive type 原始型態
    - null
    - undefined
    - string
    - number
    - boolean
    - symbol(ES6)
- Immutable
- by value

### 物件型別
- 除了以上基本型別之外都是 object type
    - array
    - function
    - data
- mutable 
- by reference
    - 例外
    
        > 若是使用 object literal 的方式來建立物件，則會變成 by Value，新增了一個記憶體的位置。


### by value、by reference、by sharing
[JavaScript 是「傳值」或「傳址」？](https://ithelp.ithome.com.tw/articles/10191057)
[談談 JavaScript 中 by reference 和 by value 的重要觀念](https://pjchender.blogspot.com/2016/03/javascriptby-referenceby-value.html)





### 如何知道型態
- typeof 
`console.log(typeof true)`

- 但有些無法靠 typeof 得知
`console.log(typepf null)` -> object
`console.log(typepf function)` -> function

- 想判斷是不是陣列
`console.log(Array.isArray([]))`
--
較舊的瀏覽器沒有這個方法的話可以用
`console.log(Object.prototype.toString,call(null))`
[object Array]


## 賦值

primitive type
object type

順帶一提
- 賦值 `=`
- 判別物件 `==`
- 多了有無型態轉換 `=== ` （指向同一個記憶體位置時才成立）


## NaN
Not a number
- 也是數字的一種，但不是真的數字
- 不等於任何東西，甚至不等於自己

isNaN 可以查是不是，但較舊瀏覽器也是不支援
[JS Comparison Table](https://dorey.github.io/JavaScript-Equality-Table/)
[isNaN()](https://developer.mozilla.org/zh-TW/docs/orphaned/Web/JavaScript/Reference/Global_Objects/isNaN#%E6%8F%8F%E8%BF%B0)

## ES6
### 宣告方式
- let    宣告變數（與 var 差不多，但作用域僅限 block）
- const  宣告常數（宣告完就不能改變）

## 作用域 scope
變數的生存範圍
- global variable 全域變數

scope chain
inner scope -> test scope -> global scope

## Hoisting
 
 Hoisting 順序
 function -> 參數 -> variable
 
直接給例
```
console.log(age)
var age = 100

輸出結果：undefined
```
咦？照理來說，程式碼由上往下執行，不是應該 `age is not defined` 嗎？很奇怪吧，這就是 JS 中的 Hoisting，變數的宣告會被**提升**到最上面。

再來，以我目前的理解及實作，Hoisting 最重要的地方在於讓程式碼中 function 可以順利宣告及呼叫。至於變數宣告，倒是可以透過良好 coding 習慣解決的。 

 
 ## Execution context 執行環境
 
 1. 單執行緒
 2. 同步執行
 3. 只會有一個 Global Execution
 4. function Execution 沒有限制
 5. 只要呼叫函式就會建立執行環境（call function -> Execution context），即使是自己呼叫自己

| Execution context (*current*) |
| ----------------------------- |
| Execution context （N+2）     |
| Execution context （N+1）     |
| Execution context （N）       |
| Global Execution context      |


function 的資訊都在 Execution context 裡，而每個 Execution context 裡都會有相對應的 variable object（暫稱 VO）。

> 首先，你可以把 VO 想像成就是一個 JavaScript 的物件就好。

>再來，VO 什麼時候會用到？你在存取值的時候會用到，例如說 var a = 10 這一句，之前有講過可以分成左右兩塊：

> 1. var a：去 VO 裡面新增一個屬性叫做 a（如果沒有 a 這個屬性的話）並初始化成 undefined
> 2. a = 10：先在 VO 裡面找到叫做 a 的屬性，找到之後設定為 10

> 更多關於 VO.... 請左轉至 [我知道你懂 hoisting，可是你了解到多深？](https://blog.huli.tw/2018/11/10/javascript-hoisting-and-tdz/) 深入了解，大概滑鼠往下滑 10 下就到了
 
 
 [理解 Javascript 執行環境](https://andyyou.github.io/2015/04/18/what-is-the-execution-context-in-javascript/)
 
 ## Execution context more
 每 call function 一次，會建立一個新的 EC，但每次 JS 內部調用一個 EC 都會有兩個階段
 1. 建立階段 —— 當函式被呼叫但執行內部程式碼前
- 建立一個作用域鍊（scope chain）
- 建立變數、function、參數
- 設定 this 的值
2. 執行階段
- 賦值、設定 function 的參考和解譯執行程式碼 

所以如果我們把 EC 想像成一個物件的話，大概會像這樣
```
executionContextObject = {
  scopeChain: { /* 變數物件 + 所有父代執行環境物件的變數物件*/},
  variableObject: {/* 函式的參數/引數，內部的變數和函式*/ },
  this: {}
}
```


直譯器
找 call function -> 執行 funciton 前建立執行環境（EC）-> 進入建立階段 -> 
 ## Scope 作用域
 變數活性區
 - global
 - block（ES6）
 - function

[湯姆克魯斯與唐家霸王槍——變數的作用域(Scope)](https://ithelp.ithome.com.tw/articles/10203387)
 ## clouser 閉包
 [所有的函式都是閉包：談 JS 中的作用域與 Closure](https://blog.huli.tw/2018/12/08/javascript-closure/)
 
 
 ## 物件導向
 ```
 myWallet.add(1)
 ```
 以前可能是用 function call
 
 - class -> this
ES6 之前JS還沒有物件導向方法

 
- setter
getter

- ES5 時期，透過 .prototype.getName()

### prototype 原型鍊

- `prototype`
- `__proto__`
- `constructor`
- `Object.prototype`
- `Function.prototype`
- `new`

### 物件導向的繼承 Inheritance
- `constrecture`
- `super`

### this (記得先盡量搞懂物件導向)

> - this 是 JavaScript 的一個關鍵字。
> - this 是 function 執行時，自動生成的一個內部物件。
> - 隨著 function 執行場合的不同，this 所指向的值，也會有所不同。
> - 在大多數的情況下， this 代表的就是呼叫 function 的物件 (Owner Object of the function)。
> —— [What’s THIS in JavaScript ?](https://kuro.tw/posts/2017/10/12/What-is-THIS-in-JavaScript-%E4%B8%8A/)


> - 嚴格模式底下就都是undefined
> - 非嚴格模式，瀏覽器底下是window
> - 非嚴格模式，node.js 底下是global
> —— [淺談 JavaScript 頭號難題 this：絕對不完整，但保證好懂](https://blog.huli.tw/2019/02/23/javascript-what-is-this/)






~~' use strict ' ;~~

~~.call()~~
~~.apply()~~

```
function log() {
  console.log(this);
}

var a = { a: 1, log: log };
var b = { a: 2, log: log };

log();            // undefined
a.log();          // a

b.log.apply(a)    // a
```

<!-- ### 強制綁定 this bind -->




## 怎麼理解繼承？

### 文章先嗑
[Javascript继承机制的设计思想](http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html)
[Javascript 面向对象编程（一）：封装](https://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html)
[Javascript面向对象编程（二）：构造函数的继承](https://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html)
[Javascript面向对象编程（二）：构造函数的继承](https://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html)

### 嗑完文章

一開始作者設計的時候其實認為不需要設計繼承機制，但 JS 裡面所有數據類型都是對象（object），所以最後還是引入了物件導向的 new 命令，但在 Java 或 C++ 裡使用 new 命令時都會調用「類（Class）」的構造函數，但可能礙於是要做出簡易的腳本語言不增加初學者負擔，於是簡化了設計，所以在 JS 裡的 new 命令後面跟得不是 Class 而是構造函數（constructor）。

![](https://i.imgur.com/eSVP6BK.png)


但這樣會有一個缺點，就是無法共享屬性和方法造成滿大的資源浪費，因此作者決定為構造函數（constructor）設一個 prototype 屬性。

### constructor
> 为了解决从原型对象生成实例的问题，Javascript提供了一个构造函数（Constructor）模式。

>所谓"构造函数"，其实就是一个普通函数，但是内部使用了this变量。对构造函数使用new运算符，就能生成实例，并且this变量会绑定在实例对象上。

### prototype
prototype 這個屬性包含了一個對象，所有想共享的屬性、方法都放在這個對象裡; 其他不需要的就放在剛提到的構造函數裡（constructor）。

### 。。。持續理解中。。。
[該來理解 JavaScript 的原型鍊了](https://blog.huli.tw/2017/08/27/the-javascripts-prototype-chain/)

## this
[Javascript 的 this 用法](https://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html)

