[TOC]
## 編譯器理論
分詞/詞法分析 -> 解析 -> 代碼生成
## 作用域
### 理解作用域
> 作用域:收集并維護一張所有被聲明的標識符(變量)的列表,并對當前執行中的代碼如何訪問這些變量強制實施一組嚴格的規則。
### 塊作用域
`{ .. }`是為一個塊,塊作用域維護塊中的變量列表,塊作用域中的變量只在塊中有效,不會影響到外部同名變量。
### 變量提升
```
var a=1;
先聲明,后賦值。聲明是在編譯時進行,賦值是在執行時進行。
```
### TDZ
TDZ 又稱暫時性死區,指變量在作用域內已經存在,但必須在`let/const`聲明后才可以使用。
### `var`,`let`,`const`區別
* 使用`let/const`聲明的變量在聲明前存在臨時性死區(TDZ),使用會發生錯誤
* 與`var`聲明的區別是`let/const`擁有塊作用域;
* 使用 `var` 可能造成不小心定義了同名變量,使用`let`,`const`可以避免,因為`let`,`const`聲明后的變量不允許在同一作用域中重新聲明;
* const聲明的變量,其值不可改變;
* `let`和`const`全局聲明的變量不存在于`window`對象中,這與`var`聲明不同;
## 隱式轉換
基本上所有類型都可以隱式轉換為 Boolean類型。
| 數據類型 | true | false |
| --- | --- | --- |
| String | 非空字符串 | 空字符串 |
| Number | 非0的數值 | 0 、NaN |
| Array | 數組不參與比較時 | 參與比較的空數組 |
| Object | 所有對象 | |
| undefined | 無 | undefined |
| null | 無 | null |
| NaN | 無 | NaN |
## 嚴格模式
* 變量必須使用關鍵詞聲明,未聲明的變量不允許賦值
* 關鍵詞不允許做變量使用
* 變量參數不允許重復定義
## 運算
### 一元運算符
**前置操作**
`++n`,`--n`。前置操作會在表達式最先執行。
**后置操作**
`n++`,`n--`。后置操作會在表達式最后執行。
### 邏輯運算符
**優先級**
`&&`的優先級比`||`高。
## 模板字面量
使用 \` ...\` 符號包裹的字符串中可以寫入引入變量與表達式。
例:
~~~
let name = '特朗普';
console.log(`川建國同志的真名是${name}`);
~~~
## apply/call/bind
> 改變this指針,也可以理解為對象借用方法
call與apply 用于顯示的設置函數的上下文,兩個方法作用一樣都是將對象綁定到this,只是在傳遞參數上有所不同。apply 用數組傳參,call 需要分別傳參。
bind()是將函數綁定到某個對象,比如 a.bind(hd) 可以理解為將a函數綁定到hd對象上即 hd.a()。與 call/apply 不同bind不會立即執行;bind 是復制函數行為,會返回新函數。
## 對象
### 展開語法
```
//對象合并
let a = {"name":"天天","sex":1};
let b = {"age":24};
let user = {...a,...b,"address":"北京"};
console.log(user);
```
### Symbol.toPrimitive
`Symbol.toPrimitive`?是一個內置的 Symbol 值,它是作為對象的函數值屬性存在的,當一個對象轉換為對應的原始值時,會調用此函數。
```
let obj = {
num: 1,
[Symbol.toPrimitive]: function() {
return this.num;
}
};
console.log(obj+1);//2
```
### valueOf/toString
```
let obj = {
name: "天天",
num: 1,
valueOf: function() {
console.log("valueOf");
return this.num;
},
toString: function() {
console.log("toString");
return this.name;
}
};
console.log(hd + 3); //valueOf 4
console.log(`Hi,${obj}`); //toString Hi,天天
```
### 代理攔截`Proxy`
### [Reflect](https://developer.mozilla.org/zh-cn/docs/web/javascript/reference/global_objects/reflect)
### 原型鏈
定義對象的時候,就會生成一個`__proto__`,這個`__proto__`指向的是這個對象的原型,指向的是這個對象的構造函數的`prototype`
```
function A(){}
functionB(){}
let a = new A(),b = new B();
A.prototype = b;
```
```
//對象a通過函數A構造,A即為a的構造函數。
a.constructor === A //true
//a的原型指向a的構造函數的prototype
a.__proto__ === A.prototype //true
```
下面是對象a的原型鏈:
`a`-`A.prototype (b)`-`B.prototype`-`Object.prototype`-`null`
javascript中萬物皆可看成對象,函數是`Function`類的創建的實例。
比如A,它是一個函數,也是一個對象,當我們定義函數A的時候,javascript內部實際執行:
```
let A = new Function();
```
同理,`Object`,`Function`等是函數也是對象,是對象就會有原型(`__proto__`),下面是這些的原型鏈分析:

### 類
#### 生成實例對象在es5和es6中的區別與關聯性
在es5中,通過構造函數生成實例對象
```
function User(name){
this.name = name;
}
User.prototype.show = function(){}
let user = new User();
```
在es6中,通過`class`關鍵詞生成實例對象
```
class User{
constructor(name) {
this.name = name;
}
show(){}
}
let user = new User();
```
關聯點:
* es5中的構造方法`User`相當于es6中的類`User`的構造方法`constructor`,構造方法中的`this`為實例化對象,給`this`設置的屬性和方法是當前實例化對象的屬性和方法。
* es5中定義原型方法`User.prototype.show = function(){}`;es6中類中定義的普通方法即為原型方法;
#### 類的繼承
```
class User {
show() {
console.log("user.show");
}
}
class Admin extends User {
constructor(name) {
}
info() {
this.show();
}
}
let p = new Admin();
let u = new User();
console.dir(p);
```
`class`繼承內部使用原型繼承

事實上,類`Admin`繼承至類`User`,就是設置`Admin.prototype.__proto__ = User.prototype`。
下面同樣能實現繼承:
```
class User {
show() {
console.log("user.show");
}
}
class Admin {
constructor(name) {
}
info() {
this.show();
}
}
Admin.prototype.__proto__ = User.prototype;
let p = new Admin();
let u = new User();
console.dir(p);
```
#### 對象檢測
`instanceof`,`isPrototypeOf`
### Promise
#### 狀態說明
Promise包含`pending`、`fulfilled`、`rejected`三種狀態
* `pending`指初始等待狀態,初始化`promise`時的狀態
* `resolve`指已經解決,將`promise`狀態設置為`fulfilled`
* `reject`指拒絕處理,將`promise`狀態設置為`rejected`
#### 要點
```
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("操作失敗");
}, 2000);
});
const p2 = new Promise((resolve, reject) => {
resolve(p1);
}).then(
msg => {
console.log(msg);
},
error => {
console.log(error);//執行這里,“操作失敗”
}
);
```
* 如果返回值是一個`promise`,如上,`p2`中`resolve`的參數(執行成功的返回值)是`p1`,將會發生:
* `p2`的`promise`狀態會變成`p1`的`promise`狀態;
* `p2`需要等待`p1`執行完成(執行完成指p1的Promise狀態發生改變);
* `p2`的`then`方法會過繼給`p1`;
* 包含`then`方法的對象可以當作 promise來使用;
* 執行`promise`的`then`方法中的成功和失敗回調函數,其結果必然返回一個`promise`對象。可指定返回的`promise`對象,若不指定,則默認返回一個狀態為`fulfilled`的`promise`對象。若指定返回對象不是`promise`,則返回一個返回值為該對象的`promise`對象;
#### `all`
使用`Promise.all`方法可以同時執行多個并行異步操作
* 任何一個`Promise`執行失敗就會調用`catch`方法
* 適用于一次發送多個異步操作
* 參數必須是可迭代類型,如Array/Set
* 成功后返回`promise`結果的有序數組
* 非`promise`數據添加到`all`中,它將被處理成`Promise.resolve`
#### `allSettled`
`allSettled`用于處理多個`promise`,只關注執行完成,不關注是否全部執行成功,`allSettled`狀態只會是`fulfilled`。
#### `race`
使用`Promise.race()`處理容錯異步,哪個Promise先返回用哪個。
* 以最快返回的promise為準
* 如果最快返加的狀態為`rejected`那整個`promise`為`rejected`執行cache
* 如果參數不是promise,它將被處理成`Promise.resolve`
#### `async/await`
* `async/await`本質還是promise,只是更簡潔的語法糖書寫
* `async/await`使用更清晰的promise來替換 promise.then/catch 的方式
* 在函數前加上`async`,函數將返回`promise`
* 使用`await`關鍵詞后會等待`promise`完成,并返回結果
- 前端
- js學習
- 瀏覽器默認樣式
- webpack+vue
- 個人常用webpack打包依賴
- vue使用學習
- vue源碼學習
- webpack5配置babel
- 瀑布流布局
- 個人常用庫
- 其他
- centos搭建ss服務器
- ios配置Universal Links
- pdf2htmlEX使用
- python
- python操作redis
- linux部署Django
- dateutil庫(datetime模塊的擴展).md
- docker部署django
- mysql
- 基礎知識
- 常用函數
- join關聯查詢技巧
- linux
- shell備份mysql數據庫
- crontab定時任務
- centos7安裝部署gitlab服務器
- nginx安裝配置
- 收藏夾
- python
- 博客
- 工具
- 其他
- 前端