本教程操作环境:windows7系统、ECMAScript 6版、Dell G3电脑。
“es”简介
【资料图】
es全称“ECMAScript”,是根据 ECMA-262 标准实现的通用脚本语言,ECMA-262 标准主要规定了这门语言的语法、类型、语句、关键字、保留字、操作符、对象等几个部分。每次看到 ES 后面跟着数字,是 ECMAScript 的不同版本。
es6/ ES2015
es6全称ECMAScript6(ECMAScript的第6个版本),是于2015年6月正式发布的JavaScript语言的标准,正式名为ECMAScript 2015(ES2015)。它的目标是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
ECMAScript 6 目前基本成为业界标准,它的普及速度比 ES5 要快很多,主要原因是现代浏览器对 ES6 的支持相当迅速,尤其是 Chrome 和 Firefox 浏览器,已经支持 ES6 中绝大多数的特性。
在此后ECMA Script每年发布一个大版本新增加一些重要特性,我们称之为ES6+。
本文主要总结了ES2015-ES2019的主要特性,一个学习前端的童鞋应该是常用且理解的一些特性。
ES2015 的主要作用:
解决原有语法的一些不足对原有语法进行增强全新的对象、全新的方法、全新的功能全新的数据类型和数据结构ES2015 常用的环境支持情况
nodejs查询:https://node.green/浏览器查询:http://kangax.github.io/compat-table/es6/PC浏览器对ES2015的支持情况
Chrome:51 版起便可以支持 97% 的 ES6 新特性。Firefox:53 版起便可以支持 97% 的 ES6 新特性。Safari:10 版起便可以支持 99% 的 ES6 新特性。Edge:Edge 15可以支持 96% 的 ES6 新特性。Edge 14 可以支持 93% 的 ES6 新特性。IE:IE7 ~ 11 基本不支持 ES6移动端浏览器对ES2015的支持情况
iOS:10.0 版起便可以支持 99% 的 ES6 新特性。Android:基本不支持 ES6 新特性(5.1 仅支持 25%)服务器对ES2015的支持情况,具体查看:https://node.green/
Node.js:6.5 版起便可以支持 97% 的 ES6 新特性。(6.0 支持 92%)var(对比let、const)
只有全局作用域、函数作用域,不存在严格的块级作用域存在变量提升变量的声明和定义可以分开进行变量可以重复声明let(块级作用域)
存在块级作用域不能变量提升变量的声明和定义可以分开进行变量不能重复声明const 常量
存在块级作用域不能变量提升变量的声明和定义必须在同一个语句中变量不能重复声明不能修改声明过的变量值(例如:可以修改对象的属性值,不能修改对象地址)最佳实践:不用var,主用const,配合let数组解构
const [foo, bar, baz] = arrconsole.log(foo, bar, baz)const [, , baz] = arrconsole.log(baz)// 解构剩余的数组元素// 只能在最后一个位置使用扩展运算符const [foo, ...rest] = arrconsole.log(rest)// 解构时元素较少,按照顺序取元素const [foo] = arrconsole.log(foo)// 解构时设置默认值const [foo, bar, baz = 123, more = "default value"] = arrconsole.log(bar, more)
登录后复制
对象解构
const obj = { name: "zce", age: 18 }// 变量名重复时,可以重命名和设置默认值const name = "tom"const { name: objName = "jack" } = objconsole.log(objName)
登录后复制
模板字符串
支持换行符支持嵌入变量、表达式const name = "tom"// 可以通过 ${} 插入表达式,表达式的执行结果将会输出到对应位置const msg = `hey, ${name} --- ${1 + 2} ---- ${Math.random()}`console.log(msg)
登录后复制
字符串的扩展方法
includes 包含字符串startsWith 是否以某字符串开头endsWith 是否以某字符串结束const message = "Error: foo is not defined."console.log( // message.startsWith("Error") // message.endsWith(".") message.includes("foo"))
登录后复制
方法的参数默认值
在function参数后面使用=设置默认值只有当形参传递是undefined或者没有传递值时,才会设置默认值(false也不会)如果只有部分默认值,需要将设置默认值的代码放到后面;否则无法正常使用// 默认参数一定是在形参列表的最后function foo (bar,enable = true) { console.log("foo invoked - enable: ") console.log(enable)}foo(false)
登录后复制
方法的剩余参数
只能出现在形参的最后一位只能使用一次args是一个数组,区别于arguments是一个伪数组function foo (first, ...args) { console.log(args)}foo(1, 2, 3, 4)
登录后复制
展开数组
const arr = ["foo", "bar", "baz"]// console.log(// arr[0],// arr[1],// arr[2],// )// console.log.apply(console, arr)console.log(...arr)
登录后复制
箭头函数
const arr = [1, 2, 3, 4, 5, 6, 7]// arr.filter(function (item) {// return item % 2// })// 常用场景,回调函数arr.filter(i => i % 2)
登录后复制
箭头函数的简写
function(value){return value} 等价于 value=>value
登录后复制
箭头函数的this指向
普通函数的this指向调用它方法的对象箭头函数的this和它外面函数的this指向相同,即:箭头函数不会改变this的指向// 箭头函数与 this// 箭头函数不会改变 this 指向const person = { name: "tom", // sayHi: function () { // console.log(`hi, my name is ${this.name}`)//tom,this指向该函数调用者 // } sayHi: () => { console.log(`hi, my name is ${this.name}`) //undefined,this和sayHi()外面的函数this相同 }, sayHiAsync: function () { // const _this = this // setTimeout(function () { // console.log(_this.name) //这里的this为window,所以需要使用_this // }, 1000) console.log(this) setTimeout(() => { // console.log(this.name) //这里的this指向sayHiAsync里的this,即person console.log(this) }, 1000) }}person.sayHi()person.sayHiAsync()
登录后复制
对象字面量
如果属性名和值的变量名相同,可以省略一个变量方法的简写:可以省略“:function”计算属性名:属性名可以在[]里面使用任意表达式const bar = "345"const obj = { foo: 123, // bar: bar // 属性名与变量名相同,可以省略 : bar bar, // method1: function () { // console.log("method111") // } // 方法可以省略 : function method1 () { console.log("method111") // 这种方法就是普通的函数,this 指向obj。 console.log(this) }, // Math.random(): 123 // 不允许,使用[]才行 // 通过 [] 让表达式的结果作为属性名 [bar]: 123}
登录后复制
Object.assign
将源对象中的值赋值到目标对象目标对象和返回值是同一个对象如果目标对象中有相同名字的属性,则覆盖该属性可以传入多个源对象,按照顺序依次覆盖目标对象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) //true,目标对象和返回值是一个对象
登录后复制
Object.is
0 == false // => true0 === false // => false+0 === -0 // => trueNaN === NaN // => falseObject.is(+0, -0) // => falseObject.is(NaN, NaN) // => true
登录后复制
Proxy 和 Object.defineProperty
Proxy的作用对Object属性变化进行监听
对比Object.defineProperty参考笔记:https://gitee.com/ymcdhr/e-task/wikis/?sort_id=4053906
Reflect(统一的操作Object对象方法)
Proxy属性的方法中默认调用了Reflect中的方法,例如:const obj = { foo: "123", bar: "456"}const proxy = new Proxy(obj, { get (target, property) { console.log("watch logic~") // Proxy中如果不写,默认调用了此方法 return Reflect.get(target, property) }})
登录后复制
Relect提供了统一的操作Object对象的方法,MDN上有完整的13中方法:// console.log("name" in obj)// console.log(delete obj["age"])// console.log(Object.keys(obj))console.log(Reflect.has(obj, "name"))console.log(Reflect.deleteProperty(obj, "age"))console.log(Reflect.ownKeys(obj))
登录后复制
Promise
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 } // 成员变量 age = 18 // 成员函数 say () { console.log(`hi, my name is ${this.name}`) }}const p = new Person("tom")p.say()
登录后复制
Class 中的静态方法static
声明静态方法:static关键字调用静态方法:Person.say静态方法的this指向为类// static 方法class Person { constructor (name) { this.name = name } say () { console.log(`hi, my name is ${this.name}`) } static create (name) { return new Person(name) }}const tom = Person.create("tom")tom.say()
登录后复制
Class 的继承
使用extends继承注意super的使用,能够访问父类;通常用来执行父类构造函数。class Person { constructor (name) { this.name = name } say () { console.log(`hi, my name is ${this.name}`) }}class Student extends Person { constructor (name, number) { super(name) // 调用父类构造函数,否则name就没有赋值(重要) this.number = number } hello () { super.say() // 调用父类成员 console.log(`my school number is ${this.number}`) }}const s = new Student("jack", "100")s.hello()
登录后复制
Set、Map
Set 没有重复元素的数组集合
常用的成员方法
s.add(item) 添加item,返回集合本身,可链式调用s.size 获取Set的长度s.has(item)判断是否存在某个items.delete(item)删除某个items.clear()删除全部const s = new Set()s.add(1).add(2).add(3).add(4).add(2)// console.log(s)// s.forEach(i => console.log(i)) //forEach、for...of 都可以用来遍历Set// for (let i of s) {// console.log(i)// }// console.log(s.size)// console.log(s.has(100))// console.log(s.delete(3))// console.log(s)// s.clear()// console.log(s)
登录后复制
常用来数组去重
// 应用场景:数组去重const arr = [1, 2, 1, 3, 4, 1]const result1 = Array.from(new Set(arr))const result2 = [...new Set(arr)]console.log(result1,result2)
登录后复制
Map 能使用复杂结构作为属性的对象集合
以前的对象存储对象属性时,会将复杂数据转换成字符串(toString()方法),如下:
const obj = {}obj[true] = "value"obj[123] = "value"obj[{ a: 1 }] = "value"console.log(Object.keys(obj))//0: "123"//1: "true"//2: "[object Object]"
登录后复制
使用Map可以存储复杂数据作为对象属性,常用的方法有如下:
const m = new Map()const tom = { name: "tom" }m.set(tom, 90)console.log(m)console.log(m.get(tom))// m.has()// m.delete()// m.clear()// forEach可以遍历Map中的itemm.forEach((value, key) => { console.log(value, key)})
登录后复制
Symbol
一个全新的基础数据类型,每次创建都是独一无二的值
let s = Symbol();typeof s// "symbol"let s1 = Symbol("foo");let s2 = Symbol("foo");s1 === s2 // false// for方法是创建的一样的值,参数会自动转换成字符串let s3 = Symbol.for("foo");let s4 = Symbol.for("foo");s3 === s4 // true
登录后复制
可以转换为字符串,通过description(ES2019提供的方法)
let s1 = Symbol("foo");let s2 = Symbol("foo");s1 // Symbol(foo)s2 // Symbol(foo)s1 === s2 // falses1.toString() // "Symbol(foo)"s2.toString() // "Symbol(foo)"s1.description // "foo" // ES2019提供的方法
登录后复制
可以作为对象的属性名,可以避免同名冲突
const obj = {}obj[Symbol()] = "123"obj[Symbol()] = "456"console.log(obj)//Symbol(): "123"//Symbol(): "456"
登录后复制
使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中,而且不能使用点运算符
let s = Symbol();// 第一种写法let a = {};a[s] = "Hello!";// 第二种写法let a = { [s]: "Hello!"};// 以上写法都得到同样结果a[s] // "Hello!"
登录后复制
可以作为对象的私有成员,不能在外部直接访问(因为每次访问都不一样),只能通过内部this访问
// 案例2:Symbol 模拟实现私有成员// a.js ======================================const name = Symbol()const person = { [name]: "zce", say () { console.log(this[name]) }}// 只对外暴露 person// b.js =======================================// 由于无法创建出一样的 Symbol 值,// 所以无法直接访问到 person 中的「私有」成员// person[Symbol()]person.say()
登录后复制
注意:for…in、Obeject.keys、Json.stringify都无法在Symbol上使用 使用:Object.getOwnPropertySymbols,替代Obeject.keys方法用于Symbol
for…of 统一遍历方法
可以用使用break终止遍历,forEach不能跳出循环
可以遍历Array数组、Set和Map对象
普通对象不能被直接 for…of 遍历,因为它没有Symbol.iterator属性
对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。
所有可以使用 for…of 的对象都需要具有Symbol.iterator属性
// for...of 循环const arr = [100, 200, 300, 400]// for...of 循环可以替代 数组对象的 forEach 方法 但可以使用break跳出循环arr.forEach(item => { console.log(item)})for (const item of arr) { console.log(item) if (item > 100) { break }}// forEach 无法跳出循环,必须使用 some 或者 every 方法// arr.forEach() // 不能跳出循环// arr.some()// arr.every()// 遍历 Set 与遍历数组相同const s = new Set(["foo", "bar"])for (const item of s) { console.log(item)}// 遍历 Map 可以配合数组结构语法,直接获取键值const m = new Map()m.set("foo", "123")m.set("bar", "345")for (const [key, value] of m) { console.log(key, value)}// 普通对象不能被直接 for...of 遍历const obj = { foo: 123, bar: 456 }for (const item of obj) { console.log(item)}
登录后复制
可迭代接口 iterator(主要给for…of使用)
一些数据结构的原型对象 _ proto _ 中含有Symbol.iterator方法iterator方法返回一个带next()方法的指针对象每次执行next()方法,它都会返回下一个数据具有 Symbol.iterator 属性的数据结构
iterator 的遍历过程是这样的。
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。使对象能够使用 for…of
const obj = { // 使用计算属性,用[]存表达式属性名 // 1、Iterable,对象必须要有一个Symbol.iterator属性 [Symbol.iterator]: function () { return { // 2、Iterator,返回的对象有一个next()方法 next: function () { // 3、IterationResult,next()方法返回一个对象 return { value: "zce", done: true } } } }}for (const item of obj) { console.log("循环体", item)}
登录后复制
使对象能够使用 for…of,完整的代码
const obj = { store: ["foo", "bar", "baz"], [Symbol.iterator]: function () { let index = 0 const self = this 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)}
登录后复制
迭代器模式(设计模式之一)
迭代器的另外一个主要用途:迭代器模式
ES2016 新增特性
数组的includes方法
// Array.prototype.includes -----------------------------------const arr = ["foo", 1, NaN, false]// 找到返回元素下标console.log(arr.indexOf("foo"))// 找不到返回 -1console.log(arr.indexOf("bar"))// 无法找到数组中的 NaNconsole.log(arr.indexOf(NaN))// 直接返回是否存在指定元素console.log(arr.includes("foo"))// 能够查找 NaNconsole.log(arr.includes(NaN))
登录后复制
指数运算符
// 指数运算符 ---------------------------------------------------console.log(Math.pow(2, 10))console.log(2 ** 10)
登录后复制
ES2017 新增特性
Object新增方法
Object.values —— 类似Object.keys,返回对象的值数组 Object.entries —— 以数组的形式返回对象中的键值对,结合for…of可以遍历obj
const obj = { foo: "value1", bar: "value2"}// Object.values -----------------------------------------------------------console.log(Object.values(obj))// Object.entries ----------------------------------------------------------console.log(Object.entries(obj))// 比iterator 更简单,直接先将obj转换成数组,再使用 for...offor (const [key, value] of Object.entries(obj)) { console.log(key, value)}console.log(new Map(Object.entries(obj)))
登录后复制
Object.getOwnPropertyDescriptors —— 获取对象属性的完整信息,主要配合ES5的get、set使用 Object.assign 获取不到set、get信息
const p1 = { firstName: "Lei", lastName: "Wang", get fullName () { return this.firstName + " " + this.lastName }}// console.log(p1.fullName)// const p2 = Object.assign({}, p1)// p2.firstName = "zce"// console.log(p2)const descriptors = Object.getOwnPropertyDescriptors(p1)// console.log(descriptors)const p2 = Object.defineProperties({}, descriptors)p2.firstName = "zce"console.log(p2.fullName)
登录后复制
String新增方法
String.prototype.padStart / String.prototype.padEnd
const books = { html: 5, css: 16, javascript: 128}// for (const [name, count] of Object.entries(books)) {// console.log(name, count)// }for (const [name, count] of Object.entries(books)) { console.log(`${name.padEnd(16, "-")}|${count.toString().padStart(3, "0")}`)}
登录后复制
在函数参数中添加尾逗号
const arr = [ 100, 200, 300, 400,]const arr = [ 100, 200, 300]
登录后复制
新增Async/Await异步编程语法糖
1、async、await相对于generate函数升级提升的地方:
(1)内置执行器(2)更好的语义(3)更好的扩展器(4)返回值是promise2、async、await的返回值
(1)async的返回值是promise对象;但是需要注意:async function f() { return "hello world";}f().then(v => console.log(v))// "hello world"
登录后复制
(2)await返回值根据后面的参数不同而不同,有两种;3、await 后面的参数
(1)await后面跟一个promise对象;=> 返回promise对象的结果;(2)await后面跟一个值;=> 直接返回该值;4、错误处理方法
async function f() { await new Promise(function (resolve, reject) { throw new Error("出错了"); });}f().then(v => console.log(v)).catch(e => console.log(e))async function myFunction() { try { await somethingThatReturnsAPromise(); } catch (err) { console.log(err); }}// 另一种写法async function myFunction() { await somethingThatReturnsAPromise() .catch(function (err) { console.log(err); });}
登录后复制
5、并发/循环异步请求的处理
(1)如果是串行执行异步请求,需要同步等待,会比较耗时;
let foo = await getFoo();let bar = await getBar();// 1、循环里面的串行执行:async function dbFuc(db) { let docs = [{}, {}, {}]; for (let doc of docs) { await db.post(doc); }}// 2、错误的串行执行:?why?思考?forEach里面的async应该是异步同时执行的,没有await?function dbFuc(db) { //这里不需要 async let docs = [{}, {}, {}]; // 可能得到错误结果 docs.forEach(async function (doc) { await db.post(doc); });}
登录后复制
(2)并行执行——等待所有响应,再执行下一个步骤;
async function dbFuc(db) { let docs = [{}, {}, {}]; let promises = docs.map((doc) => db.post(doc)); let results = await Promise.all(promises); console.log(results);}// 或者使用下面的写法async function dbFuc(db) { let docs = [{}, {}, {}]; let promises = docs.map((doc) => db.post(doc)); let results = []; for (let promise of promises) { results.push(await promise); } console.log(results);}
登录后复制
(3)并行执行——不等待所有响应,回来一个回调一个;
// 可以不要在for里面await;也不要写成串行的回调;// 是在for里面写异步方法的调用?例如: let docs = [{}, {}, {}]; for (let doc of docs) { db.post(doc).then((res)=>{}); }
登录后复制
6、async、await原理(利用generator实现async、await)
ES2019 前定义的数据类型:8种
6+1 种原始数据类型 + bigInt(下个版本)
null
undefined
number
string
boolean
Symbol(ES2015)
BigInt(stage-4,下个版本出标准化)
【相关推荐:javascript视频教程、编程视频】
以上就是es2015就是es6吗的详细内容,更多请关注php中文网其它相关文章!