Novos recursos do ECMAScript 3

Descrição do artigo: Este artigo contém as notas e a experiência do campo de treinamento front-end de Regao. Se houver algo errado, espero que você possa apontar e ensinar, obrigado!

Um, Símbolo

  • O tipo de dados do símbolo representa um valor único, que pode ser usado para evitar o problema de duplicação do nome do atributo do objeto, e também pode usar este recurso para simular os membros privados do objeto

console.log(Symbol() === Symbol()) //false
//================================================
const obj = {}
obj[Symbol()] = '123'
obj[Symbol()] = '456'
console.log(obj) //{[Symbol()]:'123',[Symbol()]:'456}//作为对象唯一属性

//============================================================
const obj = {
    [Symbol()]:123
}
console.log(obj)//{[Symbol]:'123'}
//===================================================
const name = Symbol()
const person = {
    [name]:'zce',
    say(){
        console.log(this[name])
    }
}

person[Symbol()]// 无法访问 外部因为无法创建完全相同的Symbol,所以就无法直接访问到这个成员,这样该对象便实现了私有成员
person.say() //zce 内部可以拿到Symbol属性值的成员

Suplemento de símbolo

// Symbol 补充

console.log(
    //Symbol() === Symbol() false
    // Symbol('foo') === Symbol('foo')  false
)

const s1 = Symbol.for('foo') //该方法提供了字符串和Symbol一一对应的关系, 方法里维护了字符串和Symbol之间的对应关系
const s2 = Symbol.for('foo')
console.log(s1 === s2)// true

console.log(
    Symbol.for(true) === Symbol.for('true') //true 如果传入的不是字符串,方法里会转为字符串
)
// Symbol 提供了很多内置的Symbol常量,用来作为内部方法的标识,这些标识符可以让自定义对象实现一些js当中内置的接口
console.log(Symbol.iterator) 
console.log(Symbol.hasInstance)

const obj = {
    [Symbol.toStringTag]:'XObject' 
}
console.log(obj.toString())// [object Object]  把这样的字符串叫做对象的字符串标签,若想要对象的字符串标签

const obj = {
    [Symbol()]:'symbol value',
    foo:'normal value'
}

for(var key in obj){
    console.log(key)
}
console.log(Object.keys(obj))//['foo] 获取不到Symbol这样的一个属性名
console.log(JSON.stringify(obj)) //{"foo":"normal value"}  序列化obj为json字符串,Symbol属性也会被忽略掉

console.log(Object.getOwnPropertySymbols(obj))// 这个方法类似于Object.keys方法,Object.keys方法只能够获取对象中字符串属性名,而这个方法获取到的全是Symbol属性名

Para obter mais detalhes, visite: https://developer.mozilla.org/zh-CN/docs/Glossary/Symbol

Dois, para ... de loop

  •  O loop for percorre arrays comuns, o loop for ... in é adequado para percorrer pares de valores-chave e foreach é adequado para percorrer objetos de array. O novo loop for ... of pode ser usado como uma maneira unificada de percorrer todos estruturas de dados.
const arr = [100,200,300,400]

for(const item of arr){
    console.log(item) //100 200 300 400
}

for(const item of arr){// for of 可以用break关键词随时终结循环
    console.log(item)
    if(item > 100){
        break
    }
}

arr.forEach() //forEach无法终止遍历
arr.some() //返回true终止遍历
arr.every()// 返回false终止遍历
  • Objetos de pseudomatriz também podem ser percorridos por for..of, como objeto de argumentos, lista de nós de elemento durante a operação dom

const s = new Set(['foo','bar'])

for(const item of s){// 可用for of循环set
    console.log(item)//foo bar
}
  • Atravesse o objeto Mapa
const m = new Map()
m.set('foo','123')
m.set('bar','456')
for(const item of m){
    console.log(item)// ['foo','123]  ['bar','456'] 键和值放在数组中
}

for(const [key,value] of m){
    console.log(key,value)// foo 123  bar 456
}
  • No entanto, objetos comuns não podem ser reciclados, a razão é a seguinte
const obj = {foo:123,bar:456}

for(const item of obj){// obj不可被迭代
    console.log(item)// obj is not iterable
}

Iterator

Existem cada vez mais tipos de array estruturados no ES. Set e Map foram adicionados. Para fornecer um método de travessia unificado para uma variedade de estruturas de dados, o ES2015 fornece a interface Iterable, que é entendida como um padrão de especificação e atinge a uniformidade interface. A implementação da interface Iterable pode ser percorrida por ... de. [], Set, Map Existe um método Symbol (Symbol.iterator) entre os três objetos que podem ser percorridos por for ... of, e o método iterator deve ser montado nos objetos que podem ser percorridos por loop

 

Neste iterador, um ponteiro de dados deve ser mantido internamente. Cada vez que for chamado em seguida, o ponteiro se moverá um bit para trás. A função do atributo done é indicar que todos os atributos internos foram percorridos.

Para poder ser para ... de loops, você deve implementar a interface do iterador e um método do iterador deve ser montado internamente. Este método deve retornar um objeto com o método next (). Chamar este método continuamente pode atingir todos os dados. Traverse.

const Set = new Set(['foo','bar','baz'])

const iterator = Set[Symbol.iterator]()// 获取Set里面的迭代器

console.log(iterator.next()) // {value:'foo',done:false}
console.log(iterator.next()) // {value:'bar',done:false}
console.log(iterator.next()) //{value:'baz',done:false}
console.log(iterator.next())//{value:undefined,done:true}
console.log(iterator.next())//{value:undefined,done:true}

Três, realize a interface iterável mencionada acima

  • Se o objeto implementa a interface Iterable, você pode usar o loop for ... of

const obj = {//外层为自定义对象,实现了可迭代接口,称为Iterable
    [Symbol.iterator]:function(){//内部必须有一个用于返回迭代器的iterator方法
        return{// iterator 方法返回的这个对象实现了迭代器接口,这个接口约定了必须要有一个用于迭代的next方法
            next:function (){
                return{// next方法当中返回的对象,这个对象实现的是迭代结果接口,称为IterationResult,这个对象内部必须要有value属性,表示当前被迭代的数据,它的值可以使任意类型,
//除此之外还必须要有个done的布尔值用来表示 迭代是否结束
                    value:'zce',
                    done:true
                }
            }
        }
    }
}

for(const item of obj){
    console.log('循环体') //未报错
}
  • Objetos comuns podem ser executados em loop após a adição de uma interface iterativa e a inserção de dados.

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) //循环体  foo    循环体 bar  循环体  baz
}

Quatro, padrão de design do iterador

  • O núcleo do padrão do iterador é fornecer uma interface transversal unificada para o exterior, de modo que o exterior não precise se preocupar com a estrutura interna.

// 场景:你我协同开发一个任务清单应用

// 我的代码 =================================
const todos ={
    life:['吃饭','睡觉','打豆豆'],
    learn:['语文','数学','外语'],
    work:['喝茶'],

    each:function(callback){ // 对外提供了统一遍历的接口
        const all = [].concat(this.life,this.learn,this.work)
        for(const item of all){
            callback(item)
        }
    },
/*迭代器模式核心就是对外提供统一遍历接口,让外部不用再去关心内部的结构是怎样的,只不过上面的each方法只适用于当前对象结构.
ES2015中的迭代器,它是语言层面实现的迭代器模式,适用于任何数据结构,只需要通过代码实现iterator方法实现它的迭代逻辑就可以了 */
    [Symbol.iterator]:function(){
        const all = [...this.life,...this.learn,...this.work]
        let index = 0
        return{
            next:function(){
                return{
                    value:all[index],
                    done:index++ >= all.length
                }
            }
        }
    }
}

// 你的代码====================================

// for(const item of todos.life){
//     console.log(item)
// }

// for(const item of todos.learn){
//     console.log(item)
// }
// for(const item of todos.work){
//     console.log(item)
// }
//当前对象的统一对外遍历方法
todos.each(function(item){
    console.log(item)
})

console.log('---------------------')

for(const item of todos){
    console.log(item)
}

 Cinco, gerador ES2015 

  • O gerador ES2015 é introduzido para evitar aninhamento muito profundo de retornos de chamada na programação assíncrona e para fornecer melhores soluções de programação assíncrona

Função geradora

//Generator 函数
function * foo(){
    console.log('zce')
    return 100
}

const result = foo()
console.log(result)// Object [Generator] {} 打印了一个生成器对象
console.log(result.next()) // zce {value:100,done:true} 该返回值和迭代器的返回值一样,放到value当中
  •  A declaração de rendimento é muito semelhante a return, mas não encerra a execução do método
  • Chamar o próximo método deste objeto iniciará a execução do corpo da função desta função. Durante a execução, ele será pausado quando encontrar o rendimento. O valor após o rendimento será retornado como a estrutura de next. Se você continuar a chamar , ele continuará na posição pausada. Execute e assim por diante, finalmente feito torna-se verdadeiro

function *  foo(){
    console.log('1111')
    yield 100 //yield 语句跟return非常类似,但是不会结束掉方法的执行
    console.log('2222')
    yield 200
    console.log('3333')
    yield 300
}

const generator = foo()
//调用这个对象的next方法才会让这个函数的函数体开始执行,执行过程中遇到yield就会被暂停下来,yield后面的值会作为next的结构返回,继续调用的话,就会暂停的位置继续执行,如此下去,最后done变为true
console.log(generator.next()) // 1111 {value:100,done:false}
console.log(generator.next()) // 1111 {value:100,done:false} 222 {value:200,done:false} 
console.log(generator.next()) // 1111 {value:100,done:false} 222 {value:200,done:false} 333 {value:300,done:false} 
console.log(generator.next()) // 1111 {value:100,done:false} 222 {value:200,done:false} 333 {value:300,done:false} {value:undefined,done:true}

App gerador

Os seguintes são dois casos:

/案例1:发号器

function * createIdMaker(){
    let id = 1
    while(true){
        yield id++
    }
}

const idMaker = createIdMaker()

console.log(idMaker.next().value)//1
console.log(idMaker.next().value)//2
console.log(idMaker.next().value)//3
console.log(idMaker.next().value)//4

// 案例2 使用Generator 函数实现 iterator 方法

const todos = {
    life:['吃饭','睡觉','打豆豆'],
    learn:['语文','数学','外语'],
    life:['喝茶'],
    [Symbol.iterator]:function * (){
        const all = [...this.life,...this.learn,...this.work]
        // let index = 0 //不再需要手动返回一个迭代器对象,直接在iterator方法内部遍历所有的成员,通过yield去返回每一个被遍历到的对象
        // return {
        //     next:function(){
        //         return{
        //             value:all[index],
        //             done:index ++ >= all.length
        //         }
        //     }
        // }
        for(const item of all){
            yield item
        }
    }
}

for(const item of todos){
    console.log(item)
}

Seis, ES2016

//ECMAScript 2016  相对于2015只是一个小版本,仅包含两个小功能

//Array.prototype.includes -------------------------------
const arr =['foo',1,NaN,false]

console.log(arr.indexOf('foo'))//0 找到元素对应的下标
console.log(arr.indexOf('bar'))//没有找到指定元素则返回-1 
console.log(arr.indexOf(NaN))//这种方式判断会存在一个问题,不能够查找数组当中的NaN

console.log(arr.includes('foo')) //这种能直接返回布尔值,存在或者不存在

// 指数运算符 ---------------------------------------

console.log(Math.pow(2,10)) //1024 指数运算借助于Math.pow,2是底数,10是指数

console.log(2 ** 10) //1024

Seven, ES2017

console.log(Object.values(obj)) //['value1','value2'] 将对象的所有值放到数组里
console.log(Object.entries(obj)) // [['foo','value1'],['bar','value2']]  以数组的形式返回对象当中的所有的键值对

for(const [key,value] of Object.entries(obj)){
    console.log(key,value) //foo value1 //bar value2
}

console.log(new Map(Object.entries(obj))) //用entries方法转化为Map对象   Map{ 'foo' => 'value1','bar' => 'value2' }
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.fullName) // Lei Wang  Object.assign 复制时只是把fullName当作一个普通的属性去复制,才会出现这种情况

const descriptors = Object.getOwnPropertyDescriptors(p1)
// console.log(descriptors)
const p2 = Object.defineProperties({},descriptors)
p2.firstName = 'zce'
console.log(p2.fullName) // zce Wang
const books ={
    html:5,
    css:6,
    javascript:128
}

for(const [name,count] of Object.entries(books)){
    console.log(name,count) // name 5 //css 16 //javaScript 128
}

for(const [name,count] of Object.entries(books)){
    console.log(`${name.pad}`) // html------------|005 //css-------------|016 //javascript------|128
}
  • Adicione uma vírgula final nos parâmetros da função

function foo(
    bar,
    baz,
){

}

 

Acho que você gosta

Origin blog.csdn.net/weixin_41962912/article/details/109763774
Recomendado
Clasificación