#### let相關
##### 不能重復聲明
~~~javascript
// 不能重復聲明,var可以
let a = 'a'
let a = 'A'
// Uncaught SyntaxError: Identifier 'star' has already been declared
~~~
##### 塊級作用域
> es5中的作用域:全局、函數、eval(嚴格模式下才會有,雖然我不懂嚴格模式是啥子)
>
> let聲明的是塊級作用域,塊外不能訪問
~~~JavaScript
{
let a = '333'
console.log(a, '1')
}
console.log(a, '2') // Uncaught ReferenceError: a is not defined
~~~
##### 不存在變量提升
> 變量提升:<https://www.jianshu.com/p/24973b9db51a>
>
> ~~~JavaScript
> console.log(a); //undefined,不會報錯
> var a = 123;
> ~~~
~~~js
console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 'aaa'
~~~
##### 不影響作用域鏈

##### 小案例-for循環使用let
~~~JavaScript
let items = 'items是三個div的dom'
// 遍歷并綁定事件
for(let i=0;i<items.length;i++){
items[i].onclick = functionn(){
this.style.background = 'pink'
items[i].style.background = 'pink' // var下回報錯(報錯原因i=3超出邊界)
}
}
~~~
* 原理說明--參考鏈接:<https://www.cnblogs.com/echolun/p/10584703.html>
~~~JavaScript
//使用var聲明,得到3個3
var a = [];
for (var i = 0; i < 3; i++) {
a[i] = function () {
console.log(i);
};
}
a[0](); //3
a[1](); //3
a[2](); //3
//使用let聲明,得到0,1,2
var a = [];
for (let i = 0; i < 3; i++) {
a[i] = function () {
console.log(i);
};
}
a[0](); //0
a[1](); //1
a[2](); //2
~~~
#### const--聲明常量
* 一定要賦初始值
* 常量的值不能修改(引用地址不能修改)
* 塊級作用域
* 對于數組和對象的元素修改,不算對常量的修改(引用地址沒有修改)
* 常使用const聲明數組、對象
~~~javascript
const a = 1
a = 2 // Uncaught TypeError: Assignment to constant variable
const a = ['1','2','3']
a.push('4') // 雖然對改變了數組a,但是a的地址并沒有改變,所以沒有問題
~~~
> 參考鏈接:[https://www.cnblogs.com/minigrasshopper/p/9144223.html](https://www.cnblogs.com/minigrasshopper/p/9144223.html),[MDN說明](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/const)
>
> `const`實際上保證的,并**不是變量的值不得改動**,而是**變量指向的那個內存地址不得改動**。
>
> 對于簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同于常量。
>
> 但對于復合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指針;
>
> `const`只能保證這個指針是固定的,至于它指向的數據結構是不是可變的,就完全不能控制了。
>
> 因此,將一個對象聲明為常量必須非常小心。
#### 數組解構和對象解構
* 解構賦值:ES6允許按照一定模式從數組和對象中提取值,對變量進行賦值
~~~javascript
// 數組的解構賦值
const aaaa = ['一','二','三','四']
let [a,b,c,d] = aaaa // a='一',b='二'……
// 對象的解構賦值
const aa = {name:'yishen',age:18,school:'qinghua'}
let {name} = aa // yishen
let {age} = aa // 18
let {school} = aa // qinghua
~~~
#### 模板字符串 ``
* 內容中可以直接出現換行符號、'單引號'、"雙引號"不行
* 變量拼接
~~~javascript
let love = '愛'
let str = `${love}你哦!`
console.log(str) // 愛你哦!
~~~
#### 簡化對象寫法
> ES6允許在大括號里面,直接寫入變量和函數,作為對象的屬性和方法,書寫更簡潔
~~~JavaScript
let name = 'yishen'
let change = function(){
console.log('yishen')
}
const school = {
name:name,
change:chage,
improve:function(){
console.log('提升')
}
}
// 等價于
const school = {
name,
change,
improve(){
console.log('提升')
}
}
~~~
#### 箭頭函數 =>
~~~javascript
let fn = function(a,b){
return a+b
}
let fn = (a,b) => { // 當參數有且只有一個參數,小括號可以省略
return a+b
}
~~~
參考鏈接:[MDN-箭頭函數](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions),[this指向問題](https://www.jianshu.com/p/fcfda0868ec2),[this指向問題](https://www.imooc.com/article/288214?block_id=tuijian_wz)
* 箭頭函數和普通函數區別
* this是靜態的(this始終指向函數聲明時所在作用域下的this值)
* ~~~javascript
function getName(){
console.log(this.name)
}
// 函數體內部只有一句,可以省略函數的花括號
// 如果是return ,return必須省略,語句的執行結果就是函數的返回值
let getName2 = () => console.log(this.name)
// 設置window對象
window.name = 'yishen'
const school = {
name:'qinghua'
}
// 直接調用
getName() // yishen
getName2() // yishen
// call 方法調用 call方法可以改變this的指向
getName.call(school) // qinghua,this指向了school對象
getName2.call(school) // yishen ,this執行依然是window(函數聲明時所在作用域下的this)
~~~
* 不能作為構造實例化對象

`Uncaught TypeError:Person is not a constructor`
* 不能使用 arguments 變量
* 箭頭函數適用范圍
* 箭頭函數**適合**與this無關的回調。定時器,數組的方法回調
* 箭頭函數**不適合**于this無關的回調。事件回調,對象的方法
#### 給函數參數賦初始值
##### 形參初始值
~~~JavaScript
// 形參初始值,一般位置要靠后
const add = (a,b,c=100)=> a+b+c
add(1,2) // 103
~~~
##### 與解構賦值結合
~~~JavaScript
function connect({host='127.0.0.1',username,password,port=3306}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host:'mdashen.com',
username:'yishen',
password:'yishen'
})
~~~
#### rest參數
> 用于獲取函數的實參,代替[arguments](https://www.bilibili.com/video/BV1YW411T7GX?p=80)
* 傳統arguments的使用
~~~javascript
function date(){
console.log(arguments)
}
date('2','3','4') // arguments返回的是一個類數組對象,可以arguments[0]這樣用
~~~
* ES6新增,rest參數
~~~javascript
// rest參數必須放到最后
function fu (a,b,...args){
console.log(a)
console.log(b)
console.log(args)
}
fn(1,2,3,4,5,6,7) // a=1,b=2,args=[3,4,5,6,7]
~~~
#### 擴展運算符
> **...** 擴展運算符能將 **數組或對象** 轉換為逗號分隔的 **參數序列**
* 數組合并
~~~javascript
const a = [1,3,5]
const b = [2,4,6]
const c = a.concat(b) //[1, 3, 5, 2, 4, 6]
const d = [...a,...b] // [1, 3, 5, 2, 4, 6]
~~~
#### 數據類型 Symbol
##### 基本概念
> ES6引入一種新的原始數組類型Symbol,**表示獨一無二的值**。
>
> 它是javascript語言的第七種數據類型,是一種類似于字符串的數組類型
>
> * Symbol特點
> * Symbol 的值是唯一的,用來解決命名沖容的問題
> * ymbol 值不能與其他數據進行運算
> * Symbol 定義的對象屬性不能使用for.in 循環遍歷,但是可以使用 Reflect. owners 來獲取對象的所有鍵名
~~~JavaScript
// 創建Symbol
let s = Symbol()
let s2 = Symbol('描述文字,相當于對這個變量的注釋')
console.log(s, typeof s) // Symbol() "symbol"
console.log(s, typeof s2) // Symbol() "symbol"
console.log(Symbol('ddd')===Symbol('ddd')) // false
// Symbol.for創建
let s3 = Symbol.for('yishen')
let s4 = Symbol.for('yishen')
console.log(s3===s4) // true
~~~
* 補充js中數據類型,7中基本數據類型+復雜數據類型object
> USONB you are so niubility
>
> u undefined
>
> s string symbol
>
> o object
>
> n null number
>
> b boolean [BigInt](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
##### 使用場景
* 向對象中添加方法
~~~JavaScript
// 方法一
let game = {
name:'俄羅斯方塊',
up:function(){console.log('我是up方法')},
down:function(){console.log('我是down方法')}
}
let methods = {
up:Symbol(),
down:Symbol()
}
game[methods.up] = function(){
console.log('我也是up方法')
}
game[methods.down] = function(){
console.log('我也是down方法')
}
console.log(game) // 如下圖
~~~

* 給對象添加方法-------方法二

##### Symbol內置值
> 除了定義自己使用的Symbol值以外,ES6還提供了內置的Symbol值,執行語言內部使用的方法。
>
> 可以稱這些方法為魔術方法,因為它們會在特定的場 景下自動執行。
| Symbol.hasInstance | 當其他對象使用 instanceof 運算符,判斷是否為該對 象的實例時,會調用這個方法 |
| :------------------------ | ------------------------------------------------------------ |
| Symbol.isConcatSpreadable | 對象的 Symbol.isConcatSpreadable 屬性等于的是一個 布爾值,表示該對象用于 Array.prototype.concat()時,是否可以展開 |
| Symbol.species | 創建衍生對象時,會使用該屬性 |
| Symbol.match | 當執行 str.match(myObject) 時,如果該屬性存在,會 調用它,返回該方法的返回值 |
| Symbol.replace | 當該對象被 str.replace(myObject)方法調用時,會返回 該方法的返回值 |
| Symbol.search | 當該對象被 str. search (myObject)方法調用時,會返回 該方法的返回值。 |
| Symbol.split | 當該對象被 str. split (myObject)方法調用時,會返回該 方法的返回值 |
| Symbol.iterator | 對象進行 for...of 循環時,會調用 Symbol.iterator 方法, 返回該對象的默認遍歷器 |
| Symbol.toPrimitive | 該對象被轉為原始類型的值時,會調用這個方法,返 回該對象對應的原始類型值 |
| Symbol. toStringTag | 在該對象上面調用 toString 方法時,返回該方法的返 回值 |
| Symbol. unscopables | 該對象指定了使用with關鍵字時,哪些屬性會被with 環境排除。 |
* 當o instanceof Person時,hasInstance方法會自動被調用

* 可自定義返回結果


#### 迭代器
> 迭代器(iterator)是一種接口,為各種不同的數據結構提供統一的訪問機制。
>
> 任何數據結構只要部署iterator接口(對象里面的一個屬性Symbol.iterator),就可以完成遍歷操作
>
> * ES6創造了一種新的遍歷命令 for ... of 循環,iterator接口主要供 for ... of消費
> * 原生具備iterator接口的數據(可用for of 遍歷)
> * Array、Arguments、Set、Map、String、TypedArray、NodeList
> * 工作原理
> * 創建一個指針對象,指向當前數據結構的起始位置
> * 第一次調用對象的 next 方法,指針自動指向數據結構的第一個成員
> * 接下來不斷調用 next 方法,指針一直往后移動,直到指向最后一個成員
> * 每調用 next 方法返回一個包含 value 和 done 屬性的對象
> * 
> * **需要自定義遍歷數據的時候,要想到迭代器**
~~~javascript
// 迭代器應用
const beijing = {
name: '終極一班',
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
[Symbol.iterator]() {
let index = 0
let _this = this
return {
next: function () {
if (index < _this.stus.length) {
const result = {value: _this.stus[index],done: false}
index++
return result
} else {
return { value: undefined,done: true}
}
}
}
}
}
for (const v of beijing) {
console.log(v) //xiaoming xiaoning xiaotian knight
}
~~~
#### 生成器
> 生成器函數是ES6提供的一種異步編程解決方案,語法行為與傳統函數完全不同
>
> js的異步是單線程的
##### 生成器的聲明與調用
~~~JavaScript
function * gen(){
console.log(111)
yield 'yiele是代碼的分割符1'
console.log(222)
yield 'yiele是代碼的分割符2'
console.log(333)
yield 'yiele是代碼的分割符3'
console.log(444)
}
let iterator = gen()
iterator.next() // 111
iterator.next() // 222
console.log(iterator.next()) // {value:'yiele是代碼的分割符1',done:false}
console.log(iterator.next()) // {value:'yiele是代碼的分割符2',done:false}
~~~
##### 生成器的參數傳遞

* 生成器函數實例

#### Promise
> [參考鏈接](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise),
>
> Promise是ES6引入的異步編程的新解決方案。
>
> 語法上Promise是一個構造函數,用來封裝異步操作并可以獲取其成功或失敗的結果
>
> * Promise構造函數:Promise(excutor){}
> * Promise.prototype.then()
> * Promise.prototype.catch()
> .then()返回的結果也是Promise對象,對象狀態有回調函數的執行結果決定
>
> .then().then()可以鏈式調用
#### 數組結構 Set&Map
[參考鏈接-菜鳥教程](https://www.runoob.com/w3cnote/es6-map-set.html)
##### Set
> ES6提供了新的數據結構 Set(集合)。類似于數組,成員的值都是唯一的。
>
> set實現了iterator接口,可以使用 **擴展運算符** 和 **for...of**進行遍歷
>
> set的屬性和方法
>
> | size | 返回集合的元素個數 |
> | ------ | ----------------------------------------- |
> | add | 增加一個新元素,返回當前集合 |
> | delete | 刪除元素,返回boolean值 |
> | has | 檢測集合中是否包含某個元素,返回boolean值 |
> | clear | 清空集合,返回undefined |
~~~javascript
// 聲明集合set
let s = new Set(['1', 'er', 'san', 'si', 'san'])
console.log(s, typeof (s)) // Set(4){"1", "er", "san", "si"}"object"
// 集合會自動去重,可以利用這點做數組快速去重[...new Set(array)]
s.size() // ->4
s.add('wu') // ->{"1","er","san","si","wu"}
~~~
##### Map
> 它類似于對象,也是鍵值對的結合。“鍵”的范圍不限于字符串,各種類型的(包含對象)都可以當做鍵
>
> Map也實現了iterator接口,可以使用擴展運算符和for...of遍歷。
>
> Map的屬性和方法
>
> | size | 返回Map的元素個數 |
> | ----- | ---------------------------------------- |
> | set | 增加一個新元素,返回當前Map |
> | get | 返回鍵名對象的鍵值 |
> | has | 檢測Map中是否包含某個元素,返回boolean值 |
> | clear | 清空集合,返回undefined |
#### class類
> ES6提供了更接近傳統語言的寫法,引入Class 概念。
>
> 基本上ES6的class可以看做是一個[語法糖](https://baike.baidu.com/item/語法糖/5247005),其絕大多數ES5夠可以做到。
>
> 新的class寫法只是讓對象原型的寫法更加清晰,更像面向對象編程的語法
>
> 主要知識點
>
> * class聲明類
> * constructor定義構造函數初始化
> * extends繼承父類
> * super調用父級構造方法
> * static定義靜態方法和屬性(靜態方法屬于類,不屬于實例化對象)
> * 父類方法可以重寫
* ES5寫法
~~~JavaScript
function Phone(brand,price){
this.brand = brand // brand:品牌
this.price = price
}
Phone.prototype.call = function(){ // 添加方法
console.log("打電話")
}
let Huawei = new Phone('華為',4999) // 實例化對象
Huawei.call()
~~~
* ES6寫法
~~~JavaScript
class Phone{
constructor(brand,price){ // 構造方法,名字不能修改
this.brand = brand
this.price = price
}
call(){ // 方法必須使用該語法,不能使用ES5的對象完整形式
console.log('打電話')
}
}
let onePlus = new Phone("1+",4999)
onePlus.call()
~~~
* 深入研究:[鏈接](http://caibaojian.com/es6/class.html)
#### 數值擴展&對象方法擴展
##### 數值擴展
* Number.EPSION
> Number.EPSION 是 JavaScript 表示的最小精度
>
> EPSILON屬性的值接近于2.220446049250313e-16
>
> 引入一個這么小的量的目的,在于為浮點數計算,設置一個誤差范圍。我們知道浮點數計算是不精確的
~~~JavaScript
0.1+0.2 // 0.30000000000000004
function equal(a, b) {
return Math.abs(a - b) < Number.EPSILON
}
console.log(equal(0.1 + 0.1, 0.2))
console.log(0.1 + 0.2 === 0.3)
~~~
* 二進制、八進制、十進制、十六進制
~~~javascript
let b = 0b1010 // 10
let o = 0o777 // 511
let d = 100 // 100
let x = 0xff // 255
~~~
> 下面這些,在Es5中可能是單獨的方法,ES6中將其放到,對象下
>
> 舉例:ES5中 `isFinite(Infinity)` ES6中 ``Number.isFinite(Infinity)``
| Number.isFinite | 檢測一個數值是否為有限數 |
| ----------------- | -------------------------------------- |
| Number.isNan | 檢測一個數是否為NaN |
| Number.parseInt | 字符串轉數組-整數Int |
| Number.parseFloat | 字符串轉數組-浮點數Float |
| Number.isInteger | 判斷一個數是否為整數 |
| Math.trunc | 將數字的小數部分抹掉 |
| Math.sign | 檢測一個數,正數(返回1) 負數(0) 零(-1) |
##### 對象方法擴展
| Object.is | 判斷兩個值是否完全相等 |
| --------------------- | ---------------------- |
| Object.assign | 對象的合并(重復的覆蓋) |
| Object.setPrototypeOf | 設置原型對象 |
| Object.getPrototypeOf | 獲取原型對象 |
#### 模塊化
##### 基本的暴露于導入
> 模塊化值指將一個大的程序文件,拆分成許多小的文件,然后將小文件組合起來
>
> 模塊功能命令主要由兩個命令構成:
>
> * export:規定模塊的對外接口
> * import:輸入其他模塊提供的功能
* 三種暴露方式
~~~JavaScript
// 分別暴露
export let school = 'string'
export function teach(){
cosole.log('我可以教你知識')
}
// 統一暴露
let school = 'string'
function teach(){
cosole.log('我可以教你知識')
}
export {school,teach}
// 默認暴露
export default {
school:'qinghua',
change: function(){
console.log('大學期間的學識,可以改變你的一生')
}
}
~~~
* 導入方式
~~~javascript
// 通用導入方式
import * as m1 from "./m1.js"
console.log(m1.school) // string
// 解構賦值形式
import {school,teach} from "./m1.js"
console.log(school)
import {school as xuexiao } from "./m2.js" // 導入的不同模塊重名,可以使用呢as起別名
console.log(xuexiao)
import {default as m3} from './m3.js'
console.log(m3.school) // qinghua
// 簡便形式 針對默認暴露
import m3 from './m3.js'
~~~
##### babel轉化ES
> [Babel](https://www.babeljs.cn/docs/) 是一個工具鏈,主要用于將 ECMAScript 2015+ 版本的代碼轉換為向后兼容的 JavaScript 語法,以便能夠運行在當前和舊版本的瀏覽器或其他環境中
>
> 編譯打包為es5過程,局部安裝用npx 全局安裝不需要
>
> * 安裝工具 `babel-cli babel-preset-env browserify(webpack)`
> * npx babel src/js -d dist/js | 原路徑,編譯后路徑
> * 打包 npx browserify dist/app.js -o dist/bundle.js
* 使用npm
~~~javascript
import $ from 'jquery' // const $ = require('jquery')
$('body').css('background','pink')
// 后面正常編譯打包就好
~~~