1.模板字符串
模板字符串是增强的字符串 可以在字符串里解析变量
let name = '4ggg'
let age = 18
//普通的字符串
console.log('这是'+name+',今年'+age+'岁')
//模板字符串 `` 为反引号,键盘上数字1左边的符号
console.log(`这是${name},今年${age}岁`) //输出与上面等价 模板字符串的区别就是里面可以解析变量
2.数组的相关方法
2.1 copyWithin 在数组的内部去拷贝些元素放在数组的指定位置
//1 copyWithin 在数组的内部去拷贝些元素放在数组的指定位置
let arr = [1,2,3,4, 5,6]
//第二个和第三个参数就是我们要拷贝的元素的起始位置
//把下标从3到4之间的元素拷贝到下标为0的位置上
arr.copyWithin (0,3,4) ; //[4,2,3,4,5,6]
arr.copyWithin (0,3,5) ; //[4,5,3,4,5,6]
2.2 fill 用一个数字去填充整个数组
let arr2 = [1,2,3]
arr2.fill(0);
console.log(arr2) //[0,0,0]
2.3 entries,keys,values 配合for.. .of 结构去遍历数组
let arr3 = [4,5,6,7]
//打印出这个数组的所有下表 下标keys()
for (let index of arr3.keys()){
console.log(index)
}
//打印出这个数组的所有值
for (let item of arr3.values()){
console.log(item)
}
//打印出下标和值
for (let item of arr3.entries()){
console.log(item)
}
3.函数的rest参数
function func(...arg){
console.log(arg)
}
func(1,2,3,4) //打印[1,2,3,4]
function func2(a,b,...arg){
console.log(arg)
}
func2(1,2,3,4) //打印[3,4]
4.对象支持key变化
let obj = {
a:'4gg',
b:18
}
let c = 'name'
let d = 'age'
obj = {
[c]:'4ggg',
[d + '1']:18
}
5.对象新增的方法
5.1 Object.is
//Object.is 行为类似于 ===
consolt.log(Object.is('1',1)) //false
//它的出现是为了修复NaN 不等于NaN的问题
console.log(NaN === NaN) //false
console.log(Object.is(NaN,NaN)) //true
5.2 合并对象 Object.assign
let obj1 = {a:1};
let obj2 = {b:2};
let obj3 = {c:3};
let obj4 = Object.assign(obj1,obj2,obj3)
Object.assign 可以用来实现对象的浅拷贝。
6.新增的数据类型 Symbol
es5中js数据类型:
基本数据类型:数字,字符串,布尔,undefined,null,Symbol(es6新增)
引用数据类型:Object
symbol用来表示独一无二的值
//为什么要新增这个类型?
//假如别人给你一个对象 jquery对象
let obj = {
name:'44ggg',
html:function() {
alert(1)
}
}
//你拿到对象后给这个对象增加属性和方法
obj.name = 'name'
obj.html = function() {
alert(2)
}
//此时调用obj.html弹出的是2,也就是别人的对象代码被你覆盖掉了
obj.html()
//需求:让新增的属性和方法不和前面冲突
let name = Symbol();
let html = Symbol();
let obj2 = {
[name]:'xiaoli',
[html]:function() {
alert(3)
}
}
obj2[Symbol()] = '4gggg';
console.log(obj2)
console.log(name,html) //Symbol() Symbol()
//怎样去区分Symbol
let name = Symbol('name');
let html = Symbol('html');
console.log(name,html) //Symbol(name) Symbol(html)
6.1使用Symbol的注意事项
//注意1: Symbol里面的参数仅仅是对Symbol的描述,没有其他意义,因此,即使描述相同,Symbol也是不同的
console.log(Symbol('name') === Symbol('name')) //false
//但是Symbol.for方法则可以用来判断是否相同描述
console.log(Symbol.for('name') === Symbol.for('name')) //true
//注意2: Symbol函数不能使用New关键字调用
let name = new Symbol() //报错 Symbol没有构造函数
//注意3: Symbol类型在做类型转换的时候不能转成数字
console.log(String(Symbol('name'))) //Symbol(name)
console.log(Boolean(Symbol('name'))) //true
console.log(Number(Symbol('name'))) //报错
//注意4 不能做任何运算
console.log(Symbol('name') + '1') //报错
//注意5 如果把Symbol用于对象的属性和方法,一定要用一个变量来存。否则,定义的这个属性或方法不可使用
let obj = {
[Symbol('name')]:'4ggg'
}
console.log(obj[Symbol('name')]) //undefined 因为两次使用Symbol都产生了不同的东西
let name = Symbol('name')
let obj = {
[name]:'4ggg' //这里的key值一定要加[],这是es6才支持的改变对象的key值
}
console.log(obj[name]) // '4ggg'
//注意6 for in 的时候没办法遍历出来
let obj2 = {
a:1,
b:2,
[Symbol('c')]:3
[Symbol('d')]:4
}
for(let attr in obj2){
console.log(attr) //只打印出1 2
}
//可以使用Object.getOwnPropertySymbols(obj)查看对象上的所有Symbol属性
console.log(Object.getOwnPropertySymbols(obj2)) //Symbol(c) Symbol(d)
6.2Symbol内置值
除了定义自己使用的Symbol值意外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。
Symbol.hasiInstance实例:
class Person {
static[Symbol.hasInstance](param) {
console.log(param);
console.log('我被用来检测类型了');
return param.value === 1 ? true : false
}
}
let obj1 = {
value: 1
}
let obj2 = {
value: 2
}
console.log(obj1 instanceof Person);
console.log(obj2 instanceof Person);
Symbol.isConcatSpreadable实例:
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
console.log(arr1.concat(arr2));
const arr3 = [1, 2, 3]
const arr4 = [4, 5, 6]
arr4[Symbol.isConcatSpreadable] = false
console.log(arr3.concat(arr4));
其它实例请看 : https://blog.csdn.net/gxing007/article/details/79569533
7.Set数据结构
7.1 在es6中新增的数据结构 类似于数组
//集合数据类型 去重
let st = new Set([1,2,3,3,3,3,2])
console.log(st) //[1,2,3]
console.log(st.size) //3 类似于数组的length
7.2set集合数据类型中的属性
//add
let st = new Set([1,2,3,3,3,3,2])
st.add(4)
console.log(st) // [1,2,3,4]
//delete
st.delete(1)
console.log(st) // [2,3,4]
//has 查看是否存在某个元素
console.log(st.has(1)) //false
//清空所有的元素
st.clear()
console.log(st) //Set(0)
//和循环遍历相关的方法
//keys
let st2 = new Set([1,2,3,4])
console.log(st2.keys()) //1 2 3 4
console.log(st2.values()) //1 2 3 4
for(let i of st2.keys()){
console.log(i) //1 2 3 4 Set数据类型的keys方法和values方法行为是一致的
}
st2.forEach((v,k,s) =>{
console.log(v,k,s) //1 1 Set 2 2 Set 3 3 Set 4 4 Set
})
8.Map数据结构
8.1 在es6中新增的数据结构 类似于对象
let mp = new Map([
['a':1],
['b':2]
])
console.log(mp) //Map(2) {"a"=>1,"b"=>2}
console.log(mp.size) //2
//2为什么要存在Map这种数据结构
//在对象中属性名字都必须是字符串
let obj = {
"name":'4ggg',
{a:1}:'111' //报错
}
let k1 = {a:1};
let k2 = {b:1};
let obj = {
[k1]:"11", //把属性名字作为对象
[k2]:"22"
}
console.log(obj) //[object object] : "22" k1的[object object] : "11" 覆盖掉了
//Map为了解决对象的属性名不能使用对象而提出的
let mp2 = new Map([
[k1,'111'],
[k2:'222']
])
console.log(mp2) //Map {{a:1}=>"111",{b:2}=>"222"}
8.2 map类型中的属性
//set 设置键值对
let mp = new Map()
map.set('a','111')
console.log(mp) //Map(1) {"a"=>"111"}
//2.get 根据key获取到value
console.log(map.get('a')) // "111"
//3.delete 删除key
console.log(map.delete('a')) //Map(0) {}
//4.has 是否存在这个key
console.log(mp.has('a')) //false
//5.clear 清空key
mp.clear()
//6.keys 键的集合
let mp2 = new Map([
['cc':'333'],
['dd':'444']
])
console.log(mp2.keys()) //['cc','dd']
//7.循环
for(let a of mp2.keys()){
console.log(a); //cc dd
}
for(let a of mp2.values()){
console.log(a); //333 444
}
9.Promise对象
Promise对象代表一个异步 操作,有三种状态: pending (进行中)、fulilled (已成功)和rejected (已失败) ,上面代码中传入的函数有两个参数,resolve和reject, 这两个参数都是函数块,用于回调执行,resolve是将Promise的状态置为fullfiled, reject是将Promise的状态 置为rejected,只有这两个结果可以去操作Promise的状态,其他任何操作都不能更改这个状态,这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。在初学阶段你可以简单的理解为resole就是异步执行成功后被调用的函数,reject是 异步执行失败后调用的函数。
9.1 promise方法
9.1.1 all方法
all方法中传入一个数组,里面是多个Promise实例,只有当所有的Promise实例的状态变为fulilled的时候,整体的状态才会变成ufilled,这个时候每个Promise的实例返回的值会组成一个数组传给回调函数,如果整个数组中的Promise实例中有一个的状态是rejected,那么整体的状态都会是rejected,这个时候,第一个rejected实例的返回值会传给回调函数
9.1.2 race方法
promise.race方法同样是将多个Promise实例,包装成新的一个Promise实例
let p1 = new Promise(()=>{
setTimeout(()=>{
console.log('过去了1s')
},1000)
})
let p2 = new Promise(()=>{
setTimeout(()=>{
console.log('过去了2s')
},2000)
})
let p3 = new Promise(()=>{
setTimeout(()=>{
console.log('过去了3s')
},3000)
})
const p = Promise.race([p1,p2,p3]).then(()=>{
//只打印出 过去了1s
})
//上面代码中,只要p1、 p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。
//那个率先改变的Promise实例的返回值,就传递给p的回调函数。
//也就是传入race中的promise对象谁用时最少就只执行谁。
10.Iterator迭代器
10.1Iterator是一个接口名字,为不同的数据类型提供同一的访问机制(遍历操作)。任何数据结构只要部署Iterator接口,就可以完成遍历操作。
一种数据结构部署了Iterator接口 就可以被遍历(可以被迭代),就是依次去处理数据结构中的每个成员。
let arr = [1,2,3]
function Iterator(arr){
//用一个计数器来记录现在处理到哪里
let index = 0
return {
next:()=>{
//当index < arr.length
if(index < arr.length){
//index++ 自增运算符,先拿到arr[index], 再让index+1
return {value:arr[index++],done:false}
}else{
return {value:undefined,done:true}
}
}
}
}
//现在的需求 只要调用了这个Iterator接口,就可以去依次处理成员
let it = Iterator(arr)
console.log(it.next()) //{value:1,done:false}
console.log(it.next()) //{value:2,done:false}
console.log(it.next()) //{value:3,done:false}
console.log(it.next()) //{value:undefined,done:true}
//总结:遍历操作 依次取处理数据结构中的成员,就是一种机制,
//为不同的数据结构提供统一的访问规则
10.2 Iterator和for...of
一种数据结构只要部署了Iterator接口,我们就称这种数据结构是可以迭代的。在ES6中,只要是一个数据结构具有了Symbol.iterator属性,那么就认为是可迭代的,其实Symbol.iterator就是一个函数,/实现的功能和上面手写的功能差不多。在es6中很多数据类型是部署了Iterator接口的,在底层就实现了,例如: Array、 Map、Set、 String等。注意:对象是不可遍历的
let arr = [1,2,3]
//只要一种数据类型具备Symbol.iterator属性,就认为是可以迭代的,可以被循环的
console.log(arr[Symbol.iterator])
//arr[Symbol.iterator]() 这是一个函数块 ===>类似于上面写的function Iterator
let it = arr[Symbol.iterator]()
let st = "abcde"
let sit = st[Symbol.iterator]()
console.log(sit.next()) //{value:'a',done:false}
console.log(sit.next()) //{value:'b',done:false}
console.log(sit.next()) //{value:'c',done:false}
console.log(sit.next()) //{value:'d',done:false}
console.log(sit.next()) //{value:'e',done:false}
console.log(sit.next()) //{value:undefined,done:true}
10.3 Iterator的应用场景 举例
10.3.1 在解构赋值的时候默认调用Iterator接口
let arr = [1,2,3]
let [x,y,z] = arr;
10.3.2 扩展运算符使用等时候也默认调用Iterator接口
let st = 'abcde'
console.log([...st])
10.3.3 需要自定义遍历数据的时候 ,要想到迭代器
在ES6中,引入了for..of循环,作为遍历所有数据结构的统一方法,在for..of循 环内部也是调用数据结构的Symbol.iterator方法
//定义一个对象
const banji = {
name: '1班',
students: [
'xiaoming',
'uzi',
'mlxg',
'letme',
'xiaohu'
]
}
//for ... of 遍历这个对象 会报错TypeError: banji is not iterable
for (let v of banji) {
console.log(v);
}
有人会问for in 遍历不就可以了? 但是我们想要自定义遍历,需要每次遍历返回students数组里面的成员
那还有人说为什么不能banji.students.forEach() 这也可以,但是不符合面向对象的思想
//定义一个对象
const banji = {
name: '1班',
students: [
'xiaoming',
'uzi',
'mlxg',
'letme',
'xiaohu'
],
[Symbol.iterator]() {
let index = 0
return {
next: () => {
if (index < this.students.length) {
const result = {
value: this.students[index],
done: false
}
index++
return result
} else {
return {
value: undefined,
done: true
}
}
}
}
}
}
//for ... of 遍历这个对象 会报错TypeError: banji is not iterable
for (let v of banji) {
console.log(v);
}
11.Generator生成器
11.1Generator是什么?
Generator函数是ES6提供的一种异步编程解决方案(是一个函数)。在它的内部封装了多个状态,因此,又可以理解为一种状态机,执行Generator函数后返回一个迭代器对象,使用这个迭代器对象可以遍历出Generator函数内部的状态
Generator函数和传统函数的不同点有: 1函数定义的时候,function关 键字后面加 * ,2 内部使用yield关键字定义内部状态
//定义的时候和普通函数不一样 要在后面加个* 内部使用yield关键字在内部定义各种状态
function* gen(){
yield '状态1'
yield '状态2'
yield '状态3'
yield '状态4'
}
//调用generator函数后,返回的是迭代器对象 在generator函数内部,遇到yield关键字就会停止,再次调用才会往下执行找到下个yield
let it = gen() //返回的是一个可迭代对象 因此才有next方法
console.log(it.next()) //{value:'状态1',done:false}
console.log(it.next()) //{value:'状态2',done:false}
console.log(it.next()) //{value:'状态3',done:false}
console.log(it.next()) //{value:'状态4',done:false}
console.log(it.next()) //{value:undefined,done:true}
11.2 Geneator注意事项
11.2.1.generator内部代码不会马上执行,需要调用next方法的时候才去执行 如 let it = gen()不会马上执行
11.2.2.遇到yield关键字会暂停,再次调用next方法才会继续执行
11.2.3.next方法可以传参数 这个参数是yield的返回值 这个参数是上一次yield执行后的返回值
function* gen(){
console.log(1)
yield '状态1'
console.log(2)
let result = yield '状态2'
console.log(result)
console.log(3)
yield '状态3'
yield '状态4'
}
let it = gen()
it.next() //1
it.next() //2
it.next('4ggg') //'4ggg' 3 内部的状态是在调用了next方法后拿到的
11.2.4.for... of 循环gen()
for(let i of it){
console.log(i) //连续调用了4次next
}
11.2.5.对象没有Iterator接口,可以手动去部署一个
let obj = {}
obj[Symbol.iterator] = gen
for(let i of obj){
console.log(i)
}
11.3 Generator应用
应用1:
//得到一个可迭代对象
let start = gen(5)
oBtn.onclick = function(){
//点击抽奖按钮一次就运行一次next
start.next()
}
//状态机应用 先知抽奖次数 5次机会
function draw(count){
//抽奖
let prize = Math,floor(Math.random()*31)
let index = 0
let timer = setInterval(()=>{
index++
if(index === prize){
clearInterval(timer)
alert('还剩下'+(count-1)+'次机会');
return
}
},100)
}
function* gen( count){
//点击抽奖第一次
while(count > 0){
count--
yield draw(count)
}
}
应用2:异步编程:实现1s后控制台输出111 2s后输出222 3s后输出333 一共6s
//函数嵌套
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()
应用3:模拟获取 用户数据、订单数据、商品数据
function getUsersData() {
setTimeout(() => {
let data = '用户数据'
iterator.next(data)
}, 1000)
}
function getOrdersData(userData) {
setTimeout(() => {
console.log('这里获取到了用户数据:' + userData);
let data = '订单数据'
iterator.next(data)
}, 1000)
}
function getGoodsData(orderData) {
setTimeout(() => {
console.log('这里获取到了订单数据:' + orderData);
let data = '商品数据'
iterator.next(data)
}, 1000)
}
function* gen() {
let users = yield getUsersData()
console.log(users);
let orders = yield getOrdersData(users)
console.log(orders);
let goods = yield getGoodsData(orders)
console.log(goods);
}
//调用生成器函数
let iterator = gen()
iterator.next()
12. class关键字
class是js中面向对象的语法糖(es5中要通过原型来写prototype)
class Petson{
constructor(name,age){
this.name = name
this.age = age
}
showName(){
console.log(this.name,this.age)
}
}
//注意 当new Person的时候,constructor就会被执行
let p = new Person('4gg',18)
p.showName() //4gg 18
class的继承
class Parent{
constructor(name,age){
this.name = name
this.age = age
}
showName(){
console.log(this.name,this.age)
}
}
class Child extends Parent{
constructor(name,age,gender){
super(name,age) //super要放在第一行
this.gender = gender
}
}
let c2 = new Child('4ggg',18)
c2.showName() //'4ggg' 18
13ES6的数值扩展
console.log(0b1010); //二进制 10
console.log(0o20); //八进制 16
console.log(0xff); //十六进制 255
1.Number.EPSILON 是JavaScript表示的最小精度 EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
console.log(0.1 + 0.2 === 0.3); //false
function equal(a, b) {
if (Math.abs(a - b) < Number.EPSILON) {
return true
} else {
return false
}
}
console.log(equal(0.1 + 0.2, 0.3)); //true
2.二进制 八进制 十六进制
14.匿名函数自执行
//普通的函数
function fn(){
alert(1)
}
//调用
fn()
//匿名函数自执行
( function () {
alert(1)
})()
//核心:一个文件就是一个模块
var moudle = ( function () {
//私有变量
var _name = '4ggg'
function fn1(){
alert(1)
}
function fn1(){
alert(_name)
}
return{
fn1:fn1,
fn2:fn2
}
})()
console.log(moudle) //{fn1,fn2}
moudle.fn1() //1
moudle.fn2() //4ggg
console.log(moudle._name) //undefined