一、 let 声明变量
- 不能重复声明
- 有块级作用域(不影响作用域链,函数里可以拿到函数外的变量)
- 不存在变量提升
经典案列:(把for里面的var i = 0; 改成 let i = 0就好了,不然items[i]就会报错)
二、 const 声明常量
- 一定要赋初始值
- 一搬使用大写,但是小写也是可以
- 常量不能被修改
- 块级作用域
- 对数组或者对象里面的元素修改,不算对常量的修改(因为地址没有被修改)
三、变量的解构赋值
const {name,age}={name:'suzy',age:'18'}
console.log(name) // suzy
四、模板字符串
- 内容里面可以直接出现换行符
- 可以直接变量的拼接
五、 对象的简化写法 - 变量喝属性名一样时,可以简写
六、箭头函数 - this 是静态的(this指向声明时所在作用域下的this,call 也无法 改变)
- 不能作为构造函数实例化对象
- 不能使用arguments变量
- 箭头函数简写 (一个入参时可以不写括号 ,只有一行语句时 return 不要 可以放一行去)
七、函数参数的默认值(形参) - 函数参数也可以解构赋值,且也可以默认值
八、rest参数
- rest 参数必须要放到最后
function data(a,b,...args){console.log(a) // 小猫console.log(b) // 小狗console.log(args) // ['肉','鱼','草']
}
data('小猫','小狗','肉','鱼','草')
九、扩展运算符
- 数组的合并
const arr1 = [1,2,3]
const arr2 = [4,5,6]
// 之前可以用concat,arr1.concat(arr2)
// 现在通过扩展运算符也可以合并 :const arr3 = [...arr1,...arr2] // [1,2,3,4,5,6]
- 数组的浅拷贝 // const arr2 = [...arr1]
- 将伪数组转为真数组
var arr = {0:'apple',1:'banana'}
// 有3种方法将伪数组转为真数组
// 第1种:
const arr2 = Array.from(arr) // ['apple','banana']
// 第2种:
const arr2 = Array.prototype.slice.call(arr) // ['apple','banana']
// 第3种:
const arr2 = [...arr] // ['apple','banana']
十、es6 新的原始数据类型 :Symbol,表示独一无二 的值。
- Symbol值 是唯一的,用来解决命名冲突问题
// 创建symbol第一种方式:
let s1 = Symbol('苹果') // 添加标识的Symbol
let s2 = Symbol('苹果')
console.log(s1 === s2) // false
// 创建symbol第二种方式:(使用Symbol for定义)
let s3 = Symbol.for('香蕉')
let s4 = Symbol.for('香蕉')
console.log(s3 === s4) // true
- Symbol值 不能 与其他数据进行运算
- Symbol定义的对象属性不能使用 for…in 循环遍历,但是可以使用 reflect.ownkeys 来获取对象的所有键名
symbol的作用是:给对象添加属性和方法。
let game = {name:'王者荣耀',[Symbol('法师')]:function(){console.log('我是法师!') }
}
十一、Symbol内置值
- Symbol.hasInstance
class Even {static [Symbol.hasInstance](obj) {return Number(obj) % 2 === 0;}
}// 等同于
const Even = {[Symbol.hasInstance](obj) {return Number(obj) % 2 === 0;}
};1 instanceof Even // false
2 instanceof Even // true
12345 instanceof Even // false
- Symbol.isConcatSpreadable
对象的 Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。
let arr1 = ['c', 'd'];
['a', 'b'].concat(arr1, 'e') // ['a', 'b', 'c', 'd', 'e']
arr1[Symbol.isConcatSpreadable] // undefinedlet arr2 = ['c', 'd'];
arr2[Symbol.isConcatSpreadable] = false; // 表示不展开!!!
['a', 'b'].concat(arr2, 'e') // ['a', 'b', ['c','d'], 'e']
- Symbol.species
- Symbol.match
- Symbol.replace
- Symbol.search
- Symbol.split
- Symbol.iterator
- Symbol.toPrimitive
- Symbol.toStringTag
- Symbol.unscopables
十二、迭代器 - iterator
-
迭代器原理:
-
迭代器应用:
自定义遍历数据,下面列子就是可以用for…of一个对象了,迭代器里面遍历了对象里面的数组并返回了出去。
十三、生成器 - generator
注:箭头函数无法用来定义生成器函数
生成器就是一个特殊的函数,是异步编程,之前是通过回调函数实现
- 生成器函数声明和调用:
function * gen(){console.log(111)yield '小老虎'console.log(222)yield '大狮子'console.log(333)
}
for(let v of gen()){console.log(v)
}
-
生成器的函数参数 (next(‘BBB’) 可以传入实参,会 作为上一个yield语句 的返回结果)
-
生成器函数的实例1
// 回调地域写法:代码不优美且不利于维护。
setTimeOut(()=>{console.log(111)setTimeOut(()=>{console.log(222)setTimeOut(()=>{console.log(333) },3000)},2000)
},1000)// 利用生成器函数写法:
function one(){setTimeOut(()=>{console.log(111) iterator.next() },1000)
}
function two(){setTimeOut(()=>{console.log(222) iterator.next() },2000)
}
function three(){setTimeOut(()=>{console.log(333) iterator.next() },3000)
}function * gen (){yield one()yield two()yield three()
}
let iterator = gen()
iterator.next()
- 生成器函数的实例2 (利用生成器函数yield 语句完成异步调用)
// 模拟获取 用户数据->订单数据->商品数据
function getUsers(){setTimeOut(()=>{let data = ['用户数据'] iterator.next(data) // 第二个next的实参 将作为第一个yield语句的返回结果。},1000)
}
function getOrders(){setTimeOut(()=>{let data = ['订单数据'] iterator.next(data) },1000)
}
function getGoods(){setTimeOut(()=>{let data = ['商品数据'] iterator.next(data) },1000)
}
function * gen(){const userData = yield getUsers() // 这是第一个yield语句const orderData = yield getOrders()const goodData = yield getGoods()
}
let iterator = gen()
iterator.next()
十四、Promise
promise是一个构造函数,用来封装异步操作,并可以获取其成功或失败的结果
- Promise的基本使用
const p = new Promise(function(resolve,reject){setTimeOut(()=>{let data = '接口返回的数据'resolve(data) // 获取成功的数据// reject(data) // 获取失败的数据},1000)
})
p.then(function(res){// 成功
},function(reason){// 失败
})
-
读取多个文件 (通过多个then, 且 then里面是return new Promise())
-
Promise 对象 catch 方法
const p = new Promise(function(resolve,reject){setTimeOut(()=>{reject('失败了') },1000)
})
p.catch(function(reason){// 失败
}
十五、set 集合
- set集合的一些方法 :add、delete、has、clear
let s = new Set(['画画','跳舞','跳舞','唱歌'])
console.log(s.size)
s.add('弹琴')
s.delete('弹琴')
console.log(s.has('弹琴'))
s.clear()
for(let i of s){console.log(i)
}
set 里面重复的内容会被去重:
- set集合 - 数组去重 :
let arr = [1,2,1,1,4,3,5]
const res = [...new Set(arr)]
console.log(res) // [1, 2, 4, 3, 5]
- set集合 - 交集 :
let arr = [1,2,1,1,4,3,5]
let arr2 = [5,3,4,1,6,1,5]
let res = [...new Set(arr)].filter((item)=>{ // 先去重,再过滤 let s2 = new Set(arr2)if(s2.has(item)){return true }else{return false }
})// 上面的写法可以简写成这样:
let res2 = [...new Set(arr)].filter(item => new Set(arr2).has(item))
console.log(res2) // [1, 4, 3, 5]
- set集合 - 并集 : 合并之后的结果
let arr = [1,2,1,1,4,3,5]
let arr2 = [5,3,4,1,6,1,5]
let res = [...new Set([...arr,...arr2])]
console.log(res)
- set集合 - 差集 :
let arr = [1,2,3]
let arr2 = [3,4,5]
//求arr2 里面没有 arr里面有的
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)))
console.log(diff) // [1,2]
十六、Map
- Map的一些方法 :size、set、get、has、clear
- Map 可以将对象作为键,以前键只能是字符串
let m = new Map()
m.set('name','suzy')
m.set('change',function(){console.log('啦啦啦')
})
let key = {school:'清华',
}
m.set(key,['上海','北京'])
console.log(m)
console.log(m.get(key))
十七、class类
- class基本使用
// ************************** es5通过构造函数实例化对象:
function Phone(brand,price){this.brand = brandthis.price = price
}
Phone.prototype.callYou = function(){console.log('华为可以打电话给你')
}
//实例化对象
let huawei = new Phone('华为',5000)
console.log(huawei)
huawei.callYou()// ************************** 现在可以通过class这样写:
class Phone2{constructor(brand,price){this.brand = brandthis.price = price }callYou(){console.log('小米也可以打电话给你') }
}
let xiaomi = new Phone2('小米',3000)
console.log(xiaomi)
xiaomi.callYou()
- class静态成员
function Phone(){}
Phone.name = '华为' // 这个属性就是属于函数对象的,不属于实例化
let nokia = new Phone()
console.log(nokia.name) // undefined, name 是属于函数对象的静态成员,不属于这个实例对象 所以取不到class Phone2{static name = '华为' // 这个name属于静态属性static changeWorld(){console.log('我可以改变世界') }
}
let nokia = new Phone2()
console.log(nokia.name) // undefined
- es5 使用构造函数实现继承
// **************************构造函数继承***********************
function Phone(brand,price){this.brand = brandthis.price = price
}
Phone.prototype.callYou = function(){console.log('我可以打电话给你')
}function SmartPhone(brand,price,color,size){Phone.call(this,brand,price) // smartPhone 继承了 Phone 的属性方法~!!!this.color = colorthis.size = size
}
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone // 矫正 ,可以不加这行
SmartPhone.prototype.playGame = function(){console.log('我可以玩游戏')
}
const cuizi = new SmartPhone('锤子',1299,'黑色','5.5inch')
console.log(cuizi)
cuizi.callYou()
cuizi.playGame()
- class 类 实现继承
// ************************** class继承 ***********************
class Phone{// 构造方法constructor(brand,price){this.brand = brandthis.price = price }// 父类的成员属性callYou(){console.log('我可以打电话给你') }
}
class SmartPhone extends Phone { // !!!想要继承 Phoen类里面的属性需要加上:extends Phone// 构造方法constructor(brand,price,color,size){super(brand,price) // !!!! 相当于这个写法:Phone.call(this,brand,price)this.color = colorthis.size = size }playGame(){console.log('我可以玩游戏')}// !!!子类可以对父 类方法进行重写,写一样的名字即可callYou(){console.log('我是重写的方法') }
}
let xiaomi = new SmartPhone('小米',7999,'白色','4.7inch')
console.log(xiaomi)
xiaomi.callYou()
xiaomi.playGame()
- class 里面的get set
class Phone{get price(){return '5999' }set price(v){// console.log(v)}
}
let s = new Phone()
console.log(s.price)
s.price = '4999'
十八、es6 数值扩展
1.Number.EPSILON // 极小的常量
2.二进制和八进制
3.Number.isFinite() // 检查一个数值是否为有限的
4. Number.isNaN() // 用来检查一个值是否为NaN
5.Number.parseInt(), Number.parseFloat() // 字符串转整数
6.Number.isInteger() // 判断一个值是否为整数
7.Math.trunc // 将小数部分抹掉
8.Math.sign // 判断一个数到底是正数、负数、还是零(正数返回1、负数返回-1、0返回0)
十九、es6对象方法的扩展
- Object.is() // 判断2个值是否完全 相等,类似于===,不同的在于Object.is(NAN,NAN)返回true。 NAN === NAN 返回false。
- Object.assign() // 对象的合并
- Object.setPrototypeOf() // 改变/设置原型对象,不建议这么做
- Object.getPrototypeOf() // 获取原型对象
二十、模块化
-
模块化的好处:
1)防止命名冲突
2)代码复用
3)高维护性 -
模块化规范产品 ,es6之前模块化规范有:
1.ComminJS => NodeJs、Browserify
2.AMD => requireJS
3.CMD => seaJS -
es6模块化语法
模块功能主要由两个命令构成: export 和 import。
1.export 命令用于规定模块的对外接口(有3种暴露方式:分别暴露、统一暴露、默认暴露)
2.import 命令用于输入其他模块提供的功能
种暴露方式:
1.分别暴露 :每个变量前面加上 export
2.统一暴露:export {}
3.默认暴露:export default{}
引入方式:
1、通用方式:import * as m2 from “./src”;
2、结构赋值形式: import {m1,m2} from “./src”;
3、默认引入:import{default as m3} from “./src”; // m3是别名
4、简便形式:import m3 from “./src”; (针对默认暴露)
注:如果已经有相同变量了可以用 as
<script type="module"> import (school} from "./src/js/m1.js"import {school as guigu} from "./src/js/m2.js"
</script>