[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__`),下面是这些的原型链分析:
![原型链分析](https://img.kancloud.cn/f3/17/f3172bba0c41702534384e6295a9e8f4_855x633.png)
### 类
#### 生成实例对象在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`继承内部使用原型继承
![](https://img.kancloud.cn/d5/a5/d5a5f4838495182624cfa61720613aaa_512x489.png)
事实上,类`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
- 博客
- 工具
- 其他
- 前端