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
-
Para obter mais informações sobre Object.values: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/values
console.log(Object.values(obj)) //['value1','value2'] 将对象的所有值放到数组里
-
Para obter detalhes sobre Object.entries: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
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' }
-
Object.getOwnPropertyDescriptors Obtenha as informações de descrição completas das propriedades no objeto. Para obter mais detalhes, consulte: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors
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
-
String.prototype.padStart / String.prototype.padEnd Use a string fornecida para preencher a posição inicial ou final da string de destino até que a string alcance a posição especificada. Para obter detalhes, consulte: https://developer.mozilla.org/zh - CN / docs / Web / JavaScript / Reference / Global_Objects / String / padStart , https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
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,
){
}