H2 let 关键字

变量声明

js
1
2
3
4
5
6
7
8
let a;
let b,c,d;
let e =100;
let f = 521, g = 'iloveyou',h=[];

// 变量不能重复声明
let star = '123'
let star = '321' //logs error

块级作用域

js
1
2
3
4
{
let star = 'simple'
}
console.log(star); //logs 未定义,不能获取到

不存在变量提升

js
1
2
3
4
5
6
console.log(star) //logs undefined
var star = 'simple'

// 使用let
console.log(star) //logs 会直接报错,不运行提前使用变量
let star = 'simple'

H2 const 关键字

const 定义常量

注意事项

  1. 一定要赋初始值

  2. 一般常量使用大写(潜规则)

  3. 常量的值不能修改

  4. 有块级作用域

  5. 对于数组和对象的元素修改,不算做对常量的修改,不会报错

    js
    1
    2
    const TEAM = ['UZI','MXLG']
    TEAM.push('Kobe') // 允许这样修改,因为常量的地址没有变化

H2 变量的解构赋值

ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值

数组解构

js
1
2
const F4 = ['科比','姚明','奥尼尔']
let [f1,f2,f3] = F4

对象的解构

js
1
2
3
4
5
6
7
8
9
10
const obj = {
name: 'SimpleLife',
age: 18,
height: 1.88,
weight: function(){
// logs
}
}

let {name,age,height} = obj

H2 模板字符串

js
1
2
// ES6 引入新的声明字符串的方式 [``]
let star = `模板字符串`
  1. [``]内容中可以直接出现换行符
  2. 变量拼接
js
1
2
3
4
5
let str = `<ul><li>
不会报错</li></ul`

let star1 = '123';
let star2 = `${star1}前面是123`;

H2 箭头函数

js
1
2
3
4
5
6
7
8
9
10
11
// 之前声明函数
let fn = function(){

}
// ES6
let fn = (a,b)=>{

}
let fn = a => {

}

重要

  1. this值是静态的。this 始终指向函数声明时所在作用域下的 this 的值,没有自己的this
  2. 不能作为构造函数实例化对象
  3. 不能使用 arguments 变量
  4. 当形参只有一个的时候,可以简化括号。代码体只有一句,可以省略花括号
  5. 箭头函数不适合与 this 有关的回调,如事件回调,对象的方法

H2 rest 参数

js
1
2
3
4
5
6
7
8
9
10
11
12
13
//es5 获取实参的方式 arguments
function data(){
console.log(arguments)
}
data('aaa','bbb','ccc')
// 打印的结果是一个对象,且包含了实参

//es6 获取实参的方式 rest
function data(...args){
console.log(args)
}
data('aaa','bbb','ccc')
// 打印是结果是数组,可以利用函数做更多的操作

注意事项

js
1
2
3
4
5
6
7
8
// 多个参数的时候,rest参数放最后面
function fn(a,b,...args){
console(a)
console(b)
console(args)
}
fn(1,2,3,4,5,6)
//logs args数组是后面4个实参

H2 spred扩展运算符 …

js
1
2
3
4
5
6
7
const arr = ['aaa','bbb','ccc']
//通过使用 ... 将数组arr => 'aaa','bbb','ccc'
function arrobj(){
console.log(arguments)
}
arrobj(arr);//得到的不是数组
arrobj(...arr) //等同于 arrobj('aaa','bbb','ccc')

应用

  1. 合并数组

    js
    1
    2
    3
    const arr1 = ['123','456']
    const arr2 = ['789','10']
    const arr3 = [...arr1,...arr2];
  2. 将伪数组转为真正的数组

    js
    1
    2
    const divs = document.querySelectorAll('div'); //Object
    const divArr = [...divs]; // array

H2 Symbol

H3 Symbol 基本使用

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是js 语言的第一种数据类型,是一种类似字符串的数据类型

特点

  1. Symbol 的值是唯一的,用来解决命名冲突的问题
  2. 不能与其它数据进行运算
  3. Symbol 定义的对象属性不能使用 for…in 循环遍历,但是可以使用 Reflect.ownKeys 来获取对象的所有键名
js
1
2
3
4
5
6
7
8
9
// 创建Symbol
let s = Symbol()
let s1 = Symbol('simplelife')
let s2 = Symbol('simplelife') // 因为Symbol在内部实现了唯一性,故s1!=s2

// Symbol.for 创建
let s4 = Symbol.for('simplelife')
let s5 = Symbol.for('simplelife') //用这种方式创建的 s4 == s5

总结:JS数据类型

USONB: You Are So NiuBility

  1. undefined
  2. string
  3. symbol
  4. object
  5. null
  6. number
  7. boolean

Symbol 应用

  1. 给对象添加独一无二的属性和方法
js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 向对象中添加方法 up down
// 假如对象特别大复杂,你无法知道里面是否有,直接添加可能出问题
let game ={...}

// 声明一个对象
let methods = {
up: Symbol(),
down: Symbol()
}
game[methods.up] = function(){
//代码体
}
game[methods.down] = function(){
//代码体
}
js
1
2
3
4
5
6
7
8
9
10
// 第二种方式
let youxi = {
name: '狼人杀',
[Symbol('say')]: function(){
// 代码体
},
[Symbol('self')]: function(){
// 代码体
}
}

H3 Symbol 内置值


H2 迭代器

迭代器(iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 iterator 接口,就可以遍历操作

  1. ES6 创造了一种新的遍历命令 for…of 循环,iterator 接口主要提供 for…of 使用

  2. 原生具备 iterator 接口的数据(可用 for of 遍历)

    1. Array
    2. Arguments
    3. Set
    4. Map
    5. String
    6. TypeArray
    7. NodeList
  3. 工作原理

    1. 创建一个指针对象,指向当前数据结构的起始位置
    2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
    3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
    4. 每调用 next 方法放回一个包含 value 和 done 属性的对象

    注意:需要自定义遍历数据的时候,要想到迭代器

实例

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const CLASS = {
name: '终极一班',
stus:[
'小明','张三','李四','李华'
],
[Symbol.iterator](){
// 索引变量
let index = 0;
return {
next: ()=>{
if(index < this.stus.length){
const result = {value: this.stus[index],done:false}
index++;
return result;
}else{
return {value: undefined,done:true}
}
}
}
}
}
// 遍历对象
// 打印结果如下图,可以根据自己意愿去打印数组
for (let v of CLASS) {
console.log(v)
}

H2 生成器

生成器是一个特殊的函数, 实现异步编程

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 声明函数和普通函数不同,需要用分割符 *
function * fn(){
}
let iterator = fn()
fn();// 这样执行函数是没有用的
fn().next();// 调用next方法才会执行方法体
// ***************

function * fn(){
console.log(111)
yield '我是第一步';
console.log(222)
yield '我是第二步'
}
let iterator = fn()
console.log(iterator.next())
console.log(iterator.next())

H3 生成器函数参数

js
1
2
3
4
5
6
function * fn(arg){
console.log(arg)
}
// 执行获取迭代器对象
let iterator = fn('AAA');
console.log(iterator.next());

js
1
2
3
4
5
6
7
8
9
10
11
12
13
// next() 传参
function * fn(){
let one = yield 111;
console.log(one)
let two = yield 222;
console.log(two)
}
// 执行获取迭代器对象
let iterator = fn()

// 输出
console.log(iterator.next());
console.log(iterator.next('BBB'));

在第二次调用 next() 传入参数 ‘BBB’ ,改变了第一次 yield的返回值

实例:异步编程

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  // 使用生成器解决回调地狱的问题
function one(){
setTimeout(()=>{
console.log(111)
iterator.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(222)
iterator.next();
},1000)
}
function three(){
setTimeout(()=>{
console.log(333)
iterator.next();
},1000)
}
// 声明生成器函数
function * fn(){
yield one();
yield two();
yield three();
}

// 获取生成器函数对象
let iterator = fn()
iterator.next();

实例:模拟获取 用户数据 订单数据 商品数据 有先后顺序

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function getUsers(){
setTimeout(()=>{
let data = '用户数据'
// 调用next方法,并将数据传入
iterator.next(data)
})
}
function getOrders(){
setTimeout(()=>{
let data = '订单数据'
iterator.next(data)
})
}
function getGoods(){
setTimeout(()=>{
let data = '商品数据'
iterator.next(data)
})
}
function * gen(){
let users = yield getUsers();
console.log(users)
let orders = yield getOrders();
console.log(orders)
let goods = yield getGoods()
console.log(goods)
}
// 调用生成器
let iterator = gen()
iteratro.next()

第一次调用了 next() 方法 执行生成器第一段 yield后面的 getUser() 方法。该方法执行的第二次 iteratro.next(data) 并传了data数据,该data数据会改变第一段yield后面值。

H2 Promise

Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功后失败的结果

H2 Set

ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用 扩展运算符 和 for…of 进行遍历

集合的属性和方法

  1. size 返回集合的元素个数
  2. add 增加一个新元素,返回当前集合
  3. delete 删除元素,返回 boolean 值
  4. has 检查集合中是否包含某一个元素,返回 boolean 值
  5. clear 清空数组 let s = new Set(arr); s.clear()

注意

  1. let s = new Set(arr) 传入数组,有去重复性
js
1
2
let s = new Set(arr)
lert news = [...s] // 这样获取的就是一个数组

H2 Map

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是 “键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了 iterator 接口,所以可以使用 扩展运算符 和 for … of 进行遍历

Map 的属性和方法

  1. size 返回 Map 的元素个数
  2. set 增加一个新元素,返回当前 Map
  3. delete 删除元素
  4. get 返回键名对象的键值
  5. has 检测 Map 中是否包含某一个元素,返回 boolean 值
  6. clear 清空集合,返回 undefined
js
1
2
3
4
5
6
7
8
// 声明
let m = new Map()

// 添加元素
m.set('name','SimpleLife')
m.set('change',function(){
console.log('SimpleLife')
})

H2 Class 类

ES6 提供了更接近传统语言的写法,引入了 Class(类) 这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已

实例

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// ES5 构造函数写法
function Phone(brand,price){
this.brand = brand;
this.price = price;
}
// 添加方法
Phone.prototype.call = function(){
console.log('我可以打电话')
}
// 实例化对象
let Huawei = new Phone('华为',5999)
Huawei.call()
console.log(Huawei)


// ES6 class 写法
class Phone{
// 构造方法 名字不能修改
constructor(brand,price){
this.brand = brand
this.price = price
}
// ES6 class 不能写es5 声明函数的语法
call(){
console.log('我可以打电话')
}
}

let Huawei = new Phone('华为',5999)
console.log(Huawei)

静态成员:不属于实例化对象的

js
1
2
3
4
5
6
7
8
9
10
11
12
13
// ES5 声明的静态属性方法,属于函数的
function Phone(){}
Phone.name = '手机'
Phone.change = function(){ console.log('静态成员')}

// 属于实例化对象的
Phone.prototype.name = '手机'

// ES5 声明的静态属性方法,. 属于calss类的
class Phone{
static name = '手机';
static change = function(){ console.log('静态成员')}
}

H3 构造函数继承

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function Phone(brand,price){
this.brand = brand;
this.price = price
}
Phone.prototype.call = function(){
console.log('我可以打电话')
}

// 智能手机
function SmartPhone(brand,price,color,size){
Phone.call(this,brand,price)
this.color= color
this.size = size
}

// 设置子级构造函数的原型
SmartPhone.prototype = new Phone
SmartPhone.prototype.constructor = SmartPhone // 矫正

// 声明之类
SmartPhone.prototype.photo = function(){
console.log('我可以拍照')
}
SmartPhone.prototype.playGame = function(){
console.log('我可以玩游戏')
}

const huawei = new SmartPhone('华为','2200','银色','5.5inch')
console.log(huawei)

H3 类继承

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Phone{
// 构造函数
constructor(brand,price){
this.brand = brand;
this.price = price;
}

// 父类成员属性
call(){
console.log('我可以打电话')
}
}

// 通过关键字 extends 去继承
class SmartPhone extends Phone{
// 构造方法
constructor(brand,price,color,size){
// 使用super 你调父类构造函数
super(brand,price);
this.color = color;
this.size = size;
}

photo(){
console.log('拍照')
}
playGame(){
console.log('打游戏')
}
}

const xiaom = new SmartPhone('小米',799,'黑色','4.7inch')
xiaom.call()
xiaom.photo()
xiaom.playGame()

H3 子类对父类方法重写

在子类声明方法的时候,可以写同名父类方法,进行覆盖。当调用的时候,就是调用子类的方法

H3 Set 和 Get

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 在class内部设置 get 和 set
class Phone{
get price(){
console.log('价格属性被读取了')
return 'simplelife'
}

set price(value){
// set修改属性,且必须传值 value
// ……
}
}

// 实例化对象
let s = new Phone();
console.log(s.price) //logs 运行代码体,且打印return 值
s.price = 'free' //运行set

H2 数值扩展

H3 EPSILON

Number.EPSILON 是 Javascript 表示最小精度,值接近于 2.22044604925031308084726333E-16

  1. 判断相等 当两数差的绝对值小于 EPSILON 表示相等

H3 二进制和八进制

js
1
2
3
let b = 0b1010 // 表示二进制1010
let o = 0o777 // 表示八进制777
let x = 0xff // 表示十六进制

H3 Number API

  • Number.isFinite 检测一个数值是否为有限数
  • Number.isNaN 检测一个数值是否为 NaN
  • Number.parseInt Number.parseFloat 字符串转整数
  • Number.isInteger 判断一个数是否为整数
  • Math.trunc 将数字的小数部分抹掉
  • Math.sign 判断一个数到底为正数 负数 零

H2 对象方法扩展

Object.is 判断两个值是否完全相等

js
1
2
3
console.log(Object.is(150,150)) ;// ===
console.log(Object.is(NaN,Nan)) ;// logs true
console.log(NaN === NaN) // false, NaN 与任何值都不相等

Object.assign 对象的合并

js
1
2
3
4
5
6
7
const config1 = {

}
const config2 = {

}
const sum = Object.assign(config1,config2) // config2 与 config1 键名重复的,会有后面的config2覆盖

H2 模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来

**模块化的好处 **

  1. 防止命名冲突
  2. 代码复用
  3. 高维护性

模块化规范

ES6之前的模块化规范有

  1. CommonJS => NodeJS、Browserify
  2. AMD => requireJS
  3. CMD => seaJS

ES6 模块化语法

模块功能主要由两个命令构成:export 和 import

  • export 命令用于规范模块的对外接口
  • import 命令用于输入其它模块提供的功能
js
1
2
3
4
5
6
7
8
9
10
11
// foo.js
export const BLOG = 'SimpleLife'

export function teach(){
console.log(BLOG)
}

// html引入
<script type="module">
import * as f from "./foo.js"
</script>

完全暴露语法

js
1
export {BLOG,teach}

默认暴露

js
1
2
3
export default{
const BLOG = 'SimpleLife'
}

导入方式

js
1
2
3
4
5
6
7
8
9
10
11
// 通用型
import * as f from "./foo.js"

// 解构赋值形式
import {BLOG,teach} from "./foo.js"

// 默认导出是形式,导入
import {default as sm} from "./foo.js"

// 简便形式,只能用于默认导出
import sm from './foo.js'

H3 babel 对 ES6 模块化代码转换

使用 babel对项目进行打包,转换成ES5语法,使得浏览器兼容

Babel中文文档