es2015 ialah es6. Nama penuh es ialah "ECMAScript", iaitu bahasa skrip universal yang dilaksanakan mengikut piawaian ECMA-262 Versi yang dikeluarkan secara rasmi pada Jun 2015 secara rasmi dipanggil ECMAScript2015 (ES2015, kerana ia adalah versi ke-6 ECMAScript boleh Dirujuk sebagai es6.
Persekitaran pengendalian tutorial ini: sistem Windows 7, ECMAScript versi 6, komputer Dell G3.
Pengenalan kepada "es"
Nama penuh es ialah "ECMAScript", iaitu bahasa skrip universal yang dilaksanakan mengikut ECMA- 262 standard, ECMA-262 standard Ia terutamanya menetapkan sintaks, jenis, pernyataan, kata kunci, perkataan terpelihara, operator, objek dan bahagian lain bahasa. Setiap kali anda melihat ES diikuti dengan nombor, ia adalah versi ECMAScript yang berbeza.
Nama penuh es6 ialah ECMAScript6 (versi ke-6 ECMAScript Ia adalah standard bahasa JavaScript yang dikeluarkan secara rasmi pada Jun 2015. Ia adalah secara rasmi dipanggil ECMAScript 2015 (ES2015). Matlamatnya adalah untuk membolehkan bahasa JavaScript digunakan untuk menulis aplikasi berskala besar yang kompleks dan menjadi bahasa pembangunan peringkat perusahaan.
ECMAScript 6 pada asasnya telah menjadi standard industri, dan popularitinya jauh lebih pantas daripada ES5 Sebab utama ialah penyemak imbas moden menyokong ES6 dengan cepat, terutamanya pelayar Chrome dan Firefox, yang sudah menyokong kebanyakan ciri.
Selepas itu, Skrip ECMA mengeluarkan versi utama setiap tahun untuk menambah beberapa ciri penting, yang kami panggil ES6.
Artikel ini meringkaskan terutamanya ciri utama ES2015-ES2019 Kasut kanak-kanak untuk pembelajaran bahagian hadapan haruslah beberapa ciri yang biasa digunakan dan difahami.
Promise, Proxy, Object.assign, dll.
Simbol, Set, Peta, dll.
Sokongan pelayan menyemak imbas PC untuk ES2015
Sokongan penyemak imbas mudah alih untuk ES2015
Untuk sokongan pelayan untuk ES2015, sila semak: https://node. hijau /
const [foo, bar, baz] = arr console.log(foo, bar, baz) const [, , baz] = arr console.log(baz) // 解构剩余的数组元素 // 只能在最后一个位置使用扩展运算符 const [foo, ...rest] = arr console.log(rest) // 解构时元素较少,按照顺序取元素 const [foo] = arr console.log(foo) // 解构时设置默认值 const [foo, bar, baz = 123, more = 'default value'] = arr console.log(bar, more)
const obj = { name: 'zce', age: 18 } // 变量名重复时,可以重命名和设置默认值 const name = 'tom' const { name: objName = 'jack' } = obj console.log(objName)
const name = 'tom' // 可以通过 ${} 插入表达式,表达式的执行结果将会输出到对应位置 const msg = `hey, ${name} --- ${1 + 2} ---- ${Math.random()}` console.log(msg)
const message = 'Error: foo is not defined.' console.log( // message.startsWith('Error') // message.endsWith('.') message.includes('foo') )
// 默认参数一定是在形参列表的最后 function foo (bar,enable = true) { console.log('foo invoked - enable: ') console.log(enable) } foo(false)
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)
Pemalam: Fon Kod Fira menjadikan anak panah kelihatan lebih baik
const arr = [1, 2, 3, 4, 5, 6, 7] // arr.filter(function (item) { // return item % 2 // }) // 常用场景,回调函数 arr.filter(i => i % 2)
Singkatan fungsi anak panah
function(value){return value} 等价于 value=>value
Fungsi anak panah ini menghala ke
// 箭头函数与 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()
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是不完全的深拷贝?它究竟拷贝了多少东西?
获取不到obj中的get、set信息
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,目标对象和返回值是一个对象
0 == false // => true 0 === false // => false +0 === -0 // => true NaN === NaN // => false Object.is(+0, -0) // => false Object.is(NaN, NaN) // => true
Proxy的作用
对Object属性变化进行监听
对比Object.defineProperty
参考笔记:https://gitee.com/ymcdhr/e-task/wikis/?sort_id=4053906
const obj = { foo: '123', bar: '456' } const proxy = new Proxy(obj, { get (target, property) { console.log('watch logic~') // Proxy中如果不写,默认调用了此方法 return Reflect.get(target, property) } })
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
// 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))
// 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()
// 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 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 没有重复元素的数组集合
常用的成员方法
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中的item m.forEach((value, key) => { console.log(value, key) })
一个全新的基础数据类型,每次创建都是独一无二的值
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 // false s1.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…in 遍历键值对,forEach 存在局限性
可以用使用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) }
具有 Symbol.iterator 属性的数据结构
Array、Map、Set、String、TypedArray、函数的 arguments 对象、NodeList 对象
iterator 的遍历过程是这样的。
使对象能够使用 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) }
迭代器的另外一个主要用途:迭代器模式
数组的includes方法
// Array.prototype.includes ----------------------------------- const arr = ['foo', 1, NaN, false] // 找到返回元素下标 console.log(arr.indexOf('foo')) // 找不到返回 -1 console.log(arr.indexOf('bar')) // 无法找到数组中的 NaN console.log(arr.indexOf(NaN)) // 直接返回是否存在指定元素 console.log(arr.includes('foo')) // 能够查找 NaN console.log(arr.includes(NaN))
指数运算符
// 指数运算符 --------------------------------------------------- console.log(Math.pow(2, 10)) console.log(2 ** 10)
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...of for (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.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 ]
来自于ES2017标准;async、await能够更方便的进行异步编程,且通常需要成对使用;
1、async、await相对于generate函数升级提升的地方:
2、async、await的返回值
1、async函数返回一个 Promise 对象。
2、async函数内部return语句返回的值,会成为then方法回调函数的参数。
async function f() { return 'hello world'; } f().then(v => console.log(v)) // "hello world"
3、await 后面的参数
4、错误处理方法
如果await后面的promise异步操作出错,那么等同于async函数返回的 Promise 对象被reject。最好把await命令放在try…catch代码块中
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)
async、await底层封装起来了看不见代码实现
可以利用iterator或者generator函数,进行封装实现;参考代码:(未完待续)
6+1 种原始数据类型 + bigInt(下个版本)
null
undefined
number
string
boolean
Symbol(ES2015)
BigInt(stage-4,下个版本出标准化)
【相关推荐:javascript视频教程、编程视频】
Atas ialah kandungan terperinci Adakah es2015 sama dengan es6?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!