ES6-基础语法二
1. Symbol
1.1. Symbol介绍
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol特点:
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for…in 循环遍历, 但是可以使用Reflect.ownKeys来获取对象的所有键名
// create symbol
let s = Symbol()
console.log('s: ', s) // Symbol()
console.log('type of s: ', typeof s) // symbol
// create symbol with value
let s2 = Symbol('michael')
let s3 = Symbol('michael')
console.log('s2: ', s2) // Symbol(michael)
console.log('s3: ', s3) // Symbol(michael)
console.log(s2 === s3) // false
// create symbol with Symbol.for
let s4 = Symbol.for('michael')
let s5 = Symbol.for('michael')
console.log('s4: ', s5) // Symbol(michael)
console.log('s5: ', s5) // Symbol(michael)
console.log(s4 === s5) // true
// can not be calculated with other data
// let result = s + 100;
// let result = s > 100;
let result = s + s; // TypeError: Cannot convert a Symbol value to a number
// data type in js
// USONB you are so niubility
// u undefined
// s string symbol
// o object
// n null number
// b boolean
1.2. Symbol内置值
- Symbol.hasInstance:当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
- Symbol.isConcatSpreadable:对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。
- Symbol.species:创建衍生对象时,会使用该属性Symbol.match当执行str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。
- Symbol.replace:当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值。
- Symbol.search:当该对象被str. search (myObject)方法调用时,会返回该方法的返回值。
- Symbol.split:当该对象被str. split (myObject)方法调用时,会返回该方法的返回值。
- Symbol.iterator:对象进行for…of循环时,会调用 Symbol.iterator方法,返回该对象的默认遍历器
- Symbol.toPrimitive:该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
- Symbol. toStringTag:在该对象上面调用toString方法时 ,返回该方法的返回值
- Symbol. unscopables:该对象指定了使用with关键字时,哪些属性会被 with环境排除。
// Symbol.hasInstance
class Michael{
static [Symbol.hasInstance](param){
console.log(param)
console.log('here is the stataic method from Michael class')
return true
}
o = {}
}
let o1 = {}
console.log(o1 instanceof Michael) // true
// Symbol.isConcatSpreadable
const arr = [1,2,3]
const arr2 = [4,5,6]
console.log(arr.concat(arr2)) // [ 1, 2, 3, 4, 5, 6 ]
arr2[Symbol.isConcatSpreadable] = false
console.log(arr.concat(arr2)) // [ 1, 2, 3, [ 4, 5, 6, [Symbol(Symbol.isConcatSpreadable)]: false ] ]
2. 迭代器
2.1. 迭代介绍
迭代器(Iterator)就是一种机制。是一种接口,为各种不同的数据接口提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作
- ES6新提供了一种遍历命令for…of循环,Iterator接口主要供for…of消费
- 原生具备iterator接口的数据(可用for…of遍历)
Array
Arguments
Set
Map
String
TypedArray
NodeList - 工作原理
创建一个指针对象,指向当前数据结构的起始位置
第一次调用对象的next方法,指针自动指向数据结构的第一个成员
接下来不断调用next方法,指针一直往后移动,知道指向最后一个成员
每次调用next方法返回一个包含value和done属性的对象
Tip: 需要自定义遍历数据的时候,一般使用迭代器
// state an array
const blackpink = ['lisa', 'rose', 'jisoo', 'jenny']
// for...of
for(let item of blackpink){
console.log('girl group member: ', item)
}
let iterator = blackpink[Symbol.iterator]()
// call the next method of object
console.log(typeof iterator)
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
2.2. 自定义迭代器实现
const michael = {
name: 'michael',
members: [
'lisa',
'rose',
'jisoo',
'jenny'
],
// [Symbol.iterator](){
// // index variable
// let index = 0
// let _this = this
// return {
// next:function(){
// if (index < _this.members.length) {
// const result = { value: _this.members[index], done: false}
// index++
// return result
// }else{
// return {value:undefined, done: true}
// }
// }
// }
// }
// arrow function implement
[Symbol.iterator](){
// index variable
let index = 0
return {
next: () => {
if (index < this.members.length){
const result = {value: this.members[index], done: false}
index++
return result
}else{
return {value:undefined, done: true}
}
}
}
}
}
// iterate over the object
for (item of michael) {
console.log('member from michael: ', item)
}
3. 生成器
3.1. 生成器介绍
// generator is actually a special function
// asynchronous program , callback function
function * gen(){
console.log('first step')
yield 'return after first step'
console.log('second step')
yield 'return after second step'
console.log('third step')
yield 'return after third step'
console.log('last step')
}
let iterator = gen()
console.log('type of generator function: ', typeof iterator)
// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())
// console.log(iterator.next())
for (item of iterator) {
console.log(item)
}
3.2. 带参数生成器使用
// state generator function
function * generator(arg){
console.log(arg)
let one = yield 'first step'
console.log(one)
let two = yield 'second step'
console.log(two)
let three = yield 'third step'
console.log(three)
}
// get the iterated object
let iterator = generator('aaa')
console.log(iterator.next())
// assgin the value
console.log(iterator.next('bbb'))
console.log(iterator.next('ccc'))
console.log(iterator.next('ddd'))
3.3. 生成器解决回调地狱问题
// requirement: output 111 after 1 second, output 222 after 2 second, output 333 after 3 second
// call back hell
// output 111 after 1 second
// setTimeout(()=>{
// console.log(111)
// // output 222 after 2 second
// setTimeout(()=>{
// console.log(222)
// // output 333 after 3 second
// setTimeout(()=>{
// console.log(333)
// }, 3000)
// }, 2000)
// }, 1000)
// generator function
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.4. 生成器异步回调demo
// imitate get user data, order data, goods data
function getUsers(){
setTimeout(()=>{
let data = 'user data'
// call next method, and pass the user data
iterator.next(data)
}, 1000)
}
function getOrders(){
setTimeout(()=>{
let data = 'order data'
iterator.next(data)
}, 1000)
}
function getGoods(){
setTimeout(()=>{
let data = 'goods data'
iterator.next(data)
}, 1000)
}
// generator function
function * generator(){
let users = yield getOrders()
console.log('users: ', users)
let orders = yield getOrders()
console.log('orders: ', orders)
let goods = yield getGoods()
console.log('goods: ', goods)
}
// call the generator function
let iterator = generator()
iterator.next()
4. Promise
Promise是ES6引入的异步边恒的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
- Promise构造函数:Promise(excutor){}
- Promise.prototype.then 方法
- Promise.prototype.catch 方法
4.1 Promise基本使用
// new promise object
const p = new Promise(function(resolve, reject){
setTimeout(function(){
// let data = 'user data from DB'
// resolve(data)
// imitate error
let error = 'get data from DB error'
reject(error)
}, 1000)
})
// call the then mothod of promise object
p.then(function(value){
console.log('value: ', value)
}, function(reason){
console.log('reason: ', reason)
})
4.2. Promis封装读取文件
// import fs module
const fs = require('fs')
// 1. common method to read file
// fs.readFile('./data/learn.md', (err, data)=>{
// // throw it if there is an error
// if (err) throw err
// // print the content if read successfully
// console.log('content from learn.md: ', data.toString())
// })
// 2. use Promise object to read file
const p = new Promise(function(resolve, reject){
fs.readFile('./data/learn.md', (err, data)=>{
// call reject method if there is an error
if(err) reject(err)
// call resolve if read successfully
resolve(data)
})
})
p.then(function(value){
console.log('content from learn.md: ', value.toString())
}, function(reason){
console.log('read file error: ', reason)
})
4.3. Promis封装Ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>send AJAX request</title>
</head>
<body>
<script>
// send ajax request
const p = new Promise((resolve, reject)=>{
// 1. creat ajax object
const xhr = new XMLHttpRequest()
// 2. initialization
xhr.open('GET', 'https://0io8iqa8tj.execute-api.ap-southeast-1.amazonaws.com/prod/applicant/company')
// 3. send request
xhr.send()
// 4. bind event, dealwith response
xhr.onreadystatechange = function(){
// state judgement
if (xhr.readyState === 4) {
// status judgement
if (xhr.status >= 200 && xhr.status < 300){
resolve(xhr.response)
} else {
reject(xhr.status)
}
}
}
})
// define callback method
p.then(function(value){
console.log('response: ', value)
}, function(reason){
console.log('request error: ', reason)
})
</script>
</body>
</html>
4.4. Promise then方法
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
let data = 'get data from server end'
resolve(data)
}, 1000)
})
// call then method return Promise object, the status of Promise object is determined by the execution result of callback method
// 1. if the result of callback method is non-Promise field and status is successful,
// the return value is the sucess valuf of Promise object
const result = p.then(value =>{
console.log(value)
return 'there is the love'
}, reason => {
console.warn(reason)
})
console.log(result) // Promise with resolve
// const result2 = p.then(value =>{
// console.log(value)
// // throw error
// throw new Error('something wrong')
// }, reason => {
// console.warn(reason)
// })
// console.log(result2) // throw new Error('something wrong')
// 2. if the result of callback method is a Promise object ,then keep the same result
const result3 = p.then(value =>{
console.log(value)
// return Promise object
return new Promise((resolve, reject)=>{
resolve('okay')
// reject('error')
})
}, reason => {
console.warn(reason)
})
console.log(result3) // return promise with resolve
4.5. Promise catch 方法
// define a Promise object
const p = new Promise((resolve, reject) => {
setTimeout(()=>{
// set the status of p object is failed, and set the failed value
reject('something wrong!!!')
}, 1000)
})
// p.then((value)=>{}, (reason)=>{
// console.error(reason)
// })
p.catch((reason) => {
console.warn(reason)
})
4.6. Promis读取多个文件实战
// import fs
const fs = require('fs')
// common method to read multiple files at the same time
// fs.readFile('./data/learn.md', (err, data)=>{
// fs.readFile('./data/poem.md', (err, data1) => {
// fs.readFile('./data/readingFeeling.md', (err, data2) => {
// let result = data + data1 + data2
// console.log(result)
// })
// })
// })
// Promise
const p = new Promise((resolve, reject) => {
// read the first file
fs.readFile('./data/learn.md', (err, data) => {
if (err) reject(err)
resolve(data)
})
})
// read the second file
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile('./data/poem.md', (err, data) => {
if (err) reject(err)
resolve([value, data])
})
})
}, reason => {
console.error(reason)
// read the third file
}).then((value) => {
return new Promise((resolve, reject) => {
fs.readFile('./data/readingFeeling.md', (err, data) => {
if(err) reject(err)
value.push(data)
resolve(value)
})
})
}, (reason) => {
console.error(reason)
}).then(value => {
console.log(value.join('/r/n'))
}, reason => {
console.error(reason)
})