ECMAScript 概述
ECMAScrpt 是 javaScript 的一种标准
ECMAScript2015
ECMAScript2015 又称 ES6 ,
- 相较于 ES5.1 版本变化较大
- 自此命名规则发生了变化
目前有些开发者习惯用 ES6 来泛指 ES5.1 后所有的新标准 例如 async await 是ES7 新增
ES6 的准备工作
- 选用启动环境: 新版浏览器或者 node 环境
- 安装 nodemon 保存后可以自行运行
ES2015(ES6) 新特性
ES2015 let 与块级作用域
ES2015 const
ES2015 数组的解构
const arr = [100, 200, 300]
// ES6 之前
const foo = arr[0]
const bar = arr[1]
const baz = arr[2]
console.log(foo,bar,baz)
// ES6
const [foo,bar,baz] = arr
ES2015 对象的解构
const obj = {name: 'zae', age: 18}
// const {name} = obj
// const name = 'tom'
// const {name: objName} = obj
// console.log(objName)
const name = 'tom'
// 可以设置默认值
const {name: objName = 'jack'} = obj
console.log(objName)
ES2015 模板字符串字面量
// 传统
// const str = "hello es2015, this is a string"
// ES6 模板字符串可以不会对换行产生影响
const str = `hello es2015,
this is a string
`
const names ='tom'
const msg = `hey, ${names} === ${1+2} ---- ${Math.random()}`
const {log} = console
log(str)
log(msg)
ES2015带标签的模板字符串
// const str = console.log`hello world`
const name = "tom";
const gender = true;
function myTagFunc(strings, name, gender) {
// console.log(strings[0]+ name + strings[1], + gender + strings[2])
const sex = gender ? "women" : "man";
return strings[0] + name + strings[1] + sex + strings[2];
}
const result = myTagFunc`hey, ${name} is a ${gender}.`;
console.log(result);
ES2015字符串的扩展方法
- includes: 判断字符串是否含有某个字符
- startWith: 判断字符串开头是否是某个字符
- startEnd: 判断字符串结尾是否是某个字符
const message = 'Error: foo is not defined.'
console.log(
message.startsWith('Error'),
message.endsWith('.'),
message.includes('foo')
)
ES2015 参数默认值
// 函数参数的默认值
// 带有默认值的参数必须放在最后
function foo (bar ,enable = true){
console.log(bar,enable)
}
foo(1)
ES2015 剩余参数
function foo (first, ...args){
console.log(first,args)
}
foo(1,2,3,4)
ES2015 展开数组
// 展开数组
const arr = ['foo','bar', 'baz']
console.log.apply(console, arr)
console.log(...arr)
ES2015 箭头函数
const inc = (n,m) => {
console.log('inc invoked')
return n + 1
}
// 普通函数
const arr = [1,2,3,4,5,6,7]
// const arrFun = arr.filter(function(item){
// console.log(item % 2)
// return item % 2
// })
// 箭头函数
const arrFun = arr.filter(item => item % 2)
console.log(arrFun)
ES2015 箭头函数与 this
const person = {
name: 'tom',
sayHi: function(){
console.log( this )
console.log(`普通函数 hi,my name is ${this.name}`)
},
sayArrowHi: () => {
console.log(this)
console.log(` 箭头函数 hi,my name is ${this.name}`)
},
sayHiAsync: function(){
setTimeout(function() {
console.log( this)
console.log(`普通延时this hi,my name is ${this.name}`)
}, 0);
},
sayHiArrowAsync: function(){
setTimeout(()=> {
console.log(this)
console.log(`箭头延时this hi,my name is ${this.name}`)
}, 0);
}
}
// this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象
// 箭头函数体内的 this 对象,就是定义 该函数时所在的作用域指向的对象 ,而不是使用时所在的作用域指向的对象。
person.sayHi()
person.sayArrowHi()
person.sayHiAsync()
person.sayHiArrowAsync()
ES2015 对象字面量的增强
对象字面量
const bar = '345'
const obj = {
foo:123,
// bar: bar,
bar,
// method1:function(){
// console.log('method111')
// },
method1(){
console.log('method1111')
},
[bar]: 123,
[Math.random]:789,
}
console.log(obj)
ES2015 对象扩展assgin
// 将源对象赋值到目标对象,如果目标对象与源对象中,有相同的值, 源对象覆盖目标对象
const source1 = {
a: 123,
b: 123
}
const source2 = {
b:789,
d:789
}
const target = {
a:456,
c:456
}
//第一个对象为目标对象, 后面对象,覆盖第一个对象
const result = Object.assign(target,source1,source2)
console.log(target)
console.log(result === target)
// 用法:复制一个全新的对象
function func(obj){
const funcObj = Object.assign({},obj)
return funcObj
}
const obj = {name: 'global obj'}
func(obj)
console.log(obj)
ES6 2015 proxy 对比 defineProterty
// defineProperty 只能监听到对象的读取和写入, 而proxy 能监听到到defineProperty 监听不到的行为,更强大
const person = {
name: 'wzy',
age: 20
}
const personProxy = new Proxy(person, {
deleteProperty(target, property){
console.log(target,property)
delete target[property]
}
})
// 优势1:监听删除属性
delete personProxy.age
console.log(person)
// 优势2:更好监听数组的操作方式
const list = []
const listProxy = new Proxy(list,{
set(target, property, value){
console.log('set', property,value)
target[property] = value
return true // 表设置成功
}
})
listProxy.push(100)
// 优势3: Proxy是以非侵入的方式监管了对象的读写,要带上属性名
const person2 = {}
Object.defineProperty(person2,'name',{
get(){
console.log('name 被访问')
return person2._name
},
set(value){
console.log('name 被设置')
person2._name = value
}
})
Object.defineProperty(person2,'age',{
get(){
console.log('age 被访问')
return person2._age
},
set(value){
console.log('age 被设置')
person2._age = value
}
})
person2.name = "wzy"
person2.age = 20
console.log(person2)
ES2015 reflect 统一对象操作 api
- Reflect 是一个静态类, 不能通过new 来构建一个实例对象, 只能调用静态类里面的方法
- Reflect 成员方法就是 Proxy 处理对象的默认实现
const obj = {
foo: '123',
bar: '456'
}
const proxy = new Proxy(obj,{
get(target,property){
return Reflect.get(target,property)
}
})
console.log(obj.foo)
const person = {
name:'wzy',
age: 20
}
// console.log('name' in person)
// console.log(delete person.name)
// console.log(Object.keys(person))
// Reflect 统一处理方式
console.log(Reflect.has(person,'name'))
console.log(Reflect.deleteProperty(person,'age'))
console.log(Reflect.ownKeys(person))
ES2015 对象扩展方法object.js
// 通常建议使用严格等号
console.log(
// NaN === NaN
Objcet.is(NaN, NaN)
)
ES2016 proxy代理对象
//原本监听对象属性, 使用definProperty
// Proxy 对象
const person = {
name:'zce',
age: 20
}
// 第一个参数为目标对象,第二个也是对象, 为代理的处理对象
const personProxy = new Proxy(person,{
get(target,property){
return property in target ? target[property]: "default"
// console.log(target,property)
// return 100
},
set(target,property,value){
console.log(target,property,value)
if(property==='age'){
if(!Number.isInteger(value)) {
throw new TypeError(`${value} is not an int`)
}
}
target[property] = value
}
})
personProxy.age = 20
console.log(personProxy.age)
console.log(personProxy.hhh)
ES2015 Promise
javaScript 异步编程中详细介绍
ES2015 Class 类
// class 类
// function Person (name){
// this.name = name
// }
// Person.prototype.say = function(){
// console.log(`hi, my name is ${this.name}`)
// }
class Person {
// 当前类型的构造函数
constructor(name) {
this.name = name;
}
say() {
console.log(`hi, my name is ${this.name}`);
}
// 静态方法
static create(name) {
return new Person(name);
}
}
const p = new Person("wzy");
const tom = Person.create("tom");
tom.say();
// 继承
class Student extends Person {
constructor(name, number) {
// super 指继承父级
super(name);
this.number = number;
}
hello() {
super.say();
console.log(`my school number is ${this.number}`);
}
static create(name, number) {
return new Student(name, number);
}
}
const jack = Student.create("jack", 100);
jack.hello();
ES2015 set
/*
* @Descritption: Set 数据结构
*/
const s = new Set()
s.add(1).add(2).add(3).add(4).add(2)
// console.log(s)
// s.forEach(i => console.log(i))
// for(let i of s ){
// console.log(i)
// }
// console.log(s.size)
// console.log(s.has(100))
// console.log(s.delete(3))
s.clear()
console.log(s)
const arr = [1,2,1,2,3,4,3]
// 拷贝数组
const result = [...new Set(arr)]
// 拷贝数组
// const result = Array.from(new Set(arr))
console.log(result)
ES2015 map
map 数据结构和 对象 Object 很相似,但比 Object 写起来更严谨
// const obj = {}
// obj[true] = 'value'
// obj[123] = 'value'
// obj[{a:1}] = 'value2'
// console.log(Object.keys(obj)) // 输出结果,普通对象 设置键值时,如果键不是字符串类型, 会自动转换成字符串类型
// console.log(obj[{}])
const m = new Map()
const tom = {name : 'tom'}
m.set(tom,90)
m.set("tom",80)
console.log(m)
console.log(m.get(tom))
console.log(m.get('tom'))
分割
ES2015 Symbol
Symbol 一种全新的数据类型
/*
* @Descritption: Symbol 一种全新的原始数据类型(表示独一无二的值) 最主要的作用是为对象添加一个独一无二的属性名
*/
// shared.js ===================================
// const cache = {}
// // a.js ===================================
// cache['foo'] = Math.random()
// // b.js ===================================
// cache['foo'] = '123'
// console.log(cache)
// const s = Symbol()
// console.log(s)
// console.log(typeof s)
// console.log(
// Symbol() === Symbol()
// )
// console.log(Symbol('foo'))
// console.log(Symbol('bar'))
// console.log(Symbol('baz'))
// const obj = {
// [Symbol()]:123
// }
// console.log(obj)
// a.js ===================================
const name = Symbol()
const person = {
[name]:'zce',
say(){
console.log(this[name])
}
}
//b.js =========
person.say()
const s1 =Symbol.for('foo') // 字符串一样就完全一样
const s2 =Symbol.for('foo')
console.log(s1 === s2)
ES2015 for...of 循环
引入了全新的循环方式 for...of 循环 ,作为遍历所有数据结构的统一方式
const arr = [100,200,300,400]
// for(const item of arr){
// console.log(item)
// }
// arr.forEach(item=>{
// console.log(item)
// })
// for(const item of arr){
// console.log(item)
// if(item > 100){
// break
// }
// }
// const s = new Set(['foo','bar'] )
// for(const item of s){
// console.log(item)
// }
// const m = new Map()
// m.set('foo','123')
// m.set('bar','456')
// for(const [key,value] of m){
// console.log(key,value)
// }
const obj = {foo: 123, bar: 456}
for(const item of obj){
console.log(item) // 报错,obj is not iterable
}
ES2015 可迭代接口 iterable
ES2015 能表示的有结构的数据类型越来越多如 Object Array map set ,,为了给各种数据结构提供统一的遍历方式 ES2015提供了 iterable 接口 实现 for...of 的前提是 实现了 iterable 接口
// const set = new Set(["foo","bar","baz"])
// const iterator = set[Symbol.iterator]()
// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())
// 实现可迭代接口 (Iterable)
const obj = {
store:['foo', 'bar','baz'],
[Symbol.iterator]:function (){
const self = this
let index = 0
return {
next: function(){
const result = {
value:self.store[index],
done: index >= self.store.length
}
index++
return result
}
}
}
}
for(const item of obj){
console.log(item)
}
ES2015 iterator 迭代器设计模式
// 场景: 你我协同开发一个任务清单应用,提供统一的对外接口
// 我的代码 ======================
const todos = {
life: ['吃饭','睡觉', '打豆豆'],
learn: ['喝茶','数学','语文'],
work: ['喝茶'],
each: function (callback){
const arr = [].concat(this.life, this.learn, this.work)
for(const item of arr){
callback(item)
}
},
[Symbol.iterator]: function () {
const arr = [...this.life, ...this.learn, ...this.work]
let index = 0
return {
next: function(){
return {
value:arr[index],
done: index++ >= arr.length
}
}
}
}
}
// 你的代码 ======================
todos.each(function(item){
console.log(item)
})
console.log('--------------')
for(const item of todos){
console.log(item)
}
ES2015 生成器 Generator
引入生成器的目的, 是为了避免异步编程中回调嵌套过深,从而提供更好的异步编程方案
// function * foo (){
// console.log('zce')
// return 100
// }
// const result = foo()
// console.log(result.next())
// Generator 函数, 最大的特别就是惰性执行, 调一下, 执行一下
function * foo(){
console.log('11111')
yield 100
console.log('22222')
yield 200
console.log('33333')
yield 300
}
const generator = foo()
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
ES2015 生成器 Generator 函数 应用
发号器,每调用一次执行一次
// Generator 应用
// 案例1. 发号器
// function * createIdMaker () {
// let id = 1
// while(true){
// yield id++
// }
// }
// const idMaker = createIdMaker()
// console.log(idMaker.next())
// console.log(idMaker.next())
// console.log(idMaker.next())
// console.log(idMaker.next())
// console.log(idMaker.next())
// 使用 Generator 函数实现 iterator 方法
const todos = {
life: ['吃饭','睡觉', '打豆豆'],
learn: ['喝茶','数学','语文'],
work: ['喝茶'],
each: function (callback){
const arr = [].concat(this.life, this.learn, this.work)
for(const item of arr){
callback(item)
}
},
[Symbol.iterator]: function * () {
const arr = [...this.life, ...this.learn, ...this.work]
for(const item of arr ){
yield item
}
}
}
for (const item of todos){
console.log(item)
}
ES2015 Modules
语言层面上的模块化规范,与 javaScript 模块化规范一起详细学习
ES2016 概述
与 ES2015 相比, 小版本 两个功能点
// ES2016 增加了两个 功能点
// Array.prototype.includes --------------------
const arr = ['foo',1,NaN, false]
// console.log(arr.indexOf('foo'))
// console.log(arr.indexOf('bar'))
// console.log(arr.indexOf(NaN))
// console.log(arr.indexOf(false))
console.log(arr.includes('foo'))
console.log(arr.includes('bar'))
console.log(arr.includes(NaN))
console.log(arr.includes(false))
// 指数运算符 --------------------------------
console.log(Math.pow(2,10))
console.log(2 ** 10)
ES2017 概述
const obj = {
foo: 'value1',
bar: 'value2'
}
// Object.value --------------
console.log(Object.values(obj))
// Object.entries -----------------------
console.log(Object.entries(obj))
// Object.getOwnPropertyDescriptors ---------
// String.prototype.padStart / String.prototype.padEnd ---------
// 在函数参数中添加尾号
const arr = [
100,
200,
300,
400
]
console.log(arr.length)
// async await javaScript 中 详细讲解