ES6常用语法(下)

it2022-05-05  102

Symbol类型      ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法,新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入 Symbol的原因        ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是: undefined、 null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)        Symbol 值通过 Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突   let s = Symbol(); typeof s // "symbol" 上面代码中,变量 s就是一个独一无二的值。 typeof运算符的结果,表明变量 s是 Symbol 数据类型,而不是字符串之类的其他类型 注意, Symbol函数前不能使用 new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。 Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。   let s1 = Symbol('foo');let s2 = Symbol('bar'); s1 // Symbol(foo) s2 // Symbol(bar) s1.toString() // "Symbol(foo)" s2.toString() // "Symbol(bar)" 上面代码中, s1和 s2是两个 Symbol 值。如果不加参数,它们在控制台的输出都是 Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。   注意, Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的 Symbol函数的返回值是不相等的。     // 没有参数的情况 let s1 = Symbol(); let s2 = Symbol(); s1 === s2 // false // 有参数的情况 let s1 = Symbol('foo'); let s2 = Symbol('foo'); s1 === s2 // false 上面代码中, s1和 s2都是 Symbol函数的返回值,而且参数相同,但是它们是不相等的。 Symbol 值也可以转为布尔值,但是不能转为数值     let sym = Symbol(); Boolean(sym) // true !sym // false if (sym) { // ... } Number(sym) // TypeError sym + 2 // TypeError   作为属性名的 Symbol 由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性,能防止某一个键被不小心改写或覆盖。   // 第一种写法 let a = {}; a[mySymbol] = 'Hello!'; // 第二种写法 let a = {   [mySymbol]: 'Hello!'}; // 以上写法都得到同样结果 a[mySymbol] // "Hello!" 注意,Symbol 值作为对象属性名时,不能用点运算符。   const mySymbol = Symbol(); const a = {}; a.mySymbol = 'Hello!'; a[mySymbol] // undefined a['mySymbol'] // "Hello!" 上面代码中,因为点运算符后面总是字符串,所以不会读取 mySymbol作为标识名所指代的那个值,导致 a的属性名实际上是一个字符串,而不是一个 Symbol 值。 同理,在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。     let s = Symbol(); let obj = {   [s]: function (arg) { ... }}; obj[s](123); 上面代码中,如果 s不放在方括号中,该属性的键名就是字符串 s,而不是 s所代表的那个 Symbol 值。    
    Set和Map结构 ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。 Set 本身是一个构造函数,用来生成 Set 数据结构。   const s = new Set(); [2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)); for (let i of s) {   console.log(i);} // 2 3 5 4 //s=[2,3,5,4]  // 数组去重的方法(1)   上面代码 通过add方法向 Set 结构加入成员,结果表明 Set 结构不会添加重复的值。   Set 函数可以接受一个数组(获取dom的nodelist对象)作为参数,用来初始化。   // 例一 const set = new Set([1, 2, 3, 4, 4]);           [...set] // [1, 2, 3, 4] // 例二 const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]); items.size // 5 // 例三 const set = new Set(document.querySelectorAll('div')); set.size // 56 上面代码也展示了一种去除数组重复成员的方法。   // 去除数组的重复成员(2) [...new Set(array)] 向 Set 加入值的时候,不会发生类型转换,所以 5和 "5"是两个不同的值。Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符( ===),主要的区别是 NaN等于自身,而精确相等运算符认为 NaN不等于自身。   let set = new Set(); let a = NaN; let b = NaN; set.add(a); set.add(b); set // Set {NaN}   Set 结构的实例有以下属性 constructor:构造函数,默认就是Set函数。size:返回Set实例的成员总数。 Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面四个操作方法   - add(value):添加某个值,返回 Set 结构本身。 - delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 - has(value):返回一个布尔值,表示该值是否为Set的成员。 - clear():清除所有成员,没有返回值。   s.add(1).add(2).add(2); // 注意2被加入了两次 s.size // 2 s.has(1) // true s.has(2) // true s.has(3) // false s.delete(2); s.has(2) // false   Array.from方法可以将 Set 结构转为数组。     const items = new Set([1, 2, 3, 4, 5]); const array = Array.from(items);   Set 结构的实例默认可遍历   let set = new Set(['red', 'green', 'blue']); for (let x of set) {   console.log(x);} // red // green // blue   Set 结构的实例与数组一样,也拥有 forEach方法,用于对每个成员执行某种操作,没有返回值。     set = new Set([1, 4, 9]); set.forEach((value, key) => console.log(key + ' : ' + value)) // 1 : 1 // 4 : 4 // 9 : 9 上面代码说明, forEach方法的参数就是一个处理函数。该函数的参数与数组的 forEach一致,依次为键值、键名、集合本身(上例省略了该参数)。这里需要注意,Set 结构的键名就是键值(两者是同一个值),因此第一个参数与第二个参数的值永远都是一样的。   扩展运算符和 Set 结构相结合,就可以去除数组的重复成员。   let arr = [3, 5, 2, 2, 5, 5]; let unique = [...new Set(arr)]; // [3, 5, 2]   map结构 JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。   ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。    

Map 结构的实例有以下属性和操作方法。

(1)size 属性

  size属性返回 Map 结构的成员总数。   const map = new Map(); map.set('foo', true); map.set('bar', false); map.size // 2  

(2)set(key, value)

  set方法设置键名 key对应的键值为 value,然后返回整个 Map 结构。如果 key已经有值,则键值会被更新,否则就新生成该键。   const m = new Map(); m.set('edition', 6)      // 键是字符串 m.set(262, 'standard')    // 键是数值 m.set(undefined, 'nah')  // 键是 undefined     set方法返回的是当前的 Map对象,因此可以采用链式写法。   let map = new Map()   .set(1, 'a')   .set(2, 'b')   .set(3, 'c');     (3)get(key)   get方法读取 key对应的键值,如果找不到 key,返回 undefined。   const m = new Map(); const hello = function() {console.log('hello');}; m.set(hello, 'Hello ES6!') // 键是函数 m.get(hello) // Hello ES6!     (4)has(key)   has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。     const m = new Map(); m.set('edition', 6); m.set(262, 'standard'); m.set(undefined, 'nah'); m.has('edition')    // true m.has('years')      // false m.has(262)          // true m.has(undefined)    // true       (5)delete(key)   delete方法删除某个键,返回 true。如果删除失败,返回 false。   const m = new Map(); m.set(undefined, 'nah'); m.has(undefined)    // true m.delete(undefined) m.has(undefined)      // false   (6)clear()   clear方法清除所有成员,没有返回值。   let map = new Map(); map.set('foo', true); map.set('bar', false); map.size // 2 map.clear() map.size // 0  

Map 结构原生提供三个遍历器生成函数和一个遍历方法。

keys():返回键名的遍历器。values():返回键值的遍历器。entries():返回所有成员的遍历器。forEach():遍历 Map 的所有成员。   需要特别注意的是,Map 的遍历顺序就是插入顺序     const map = new Map([   ['F', 'no'],   ['T',  'yes'],]); for (let key of map.keys()) {   console.log(key);} // "F" // "T" for (let value of map.values()) {   console.log(value);} // "no" // "yes" for (let item of map.entries()) {   console.log(item[0], item[1]);} // "F" "no" // "T" "yes" // 或者 for (let [key, value] of map.entries()) {   console.log(key, value);} // "F" "no" // "T" "yes" // 等同于使用map.entries() for (let [key, value] of map) {   console.log(key, value);} // "F" "no" // "T" "yes" Map 结构转为数组结构,比较快速的方法是使用扩展运算符( ...)。   const map = new Map([   [1, 'one'],   [2, 'two'],   [3, 'three'],]); [...map.keys()] // [1, 2, 3] [...map.values()] // ['one', 'two', 'three'] [...map.entries()] // [[1,'one'], [2, 'two'], [3, 'three']] [...map] // [[1,'one'], [2, 'two'], [3, 'three']]  
    Generators生成器函数      Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同      Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。      执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。      形式上,Generator 函数是一个普通函数,但是有两个特征。一是, function关键字与函数名之间有一个星号;二是,函数体内部使用 yield表达式,定义不同的内部状态( yield在英语里的意思就是“产出”)   function* helloWorldGenerator() {   yield 'hello';   yield 'world';   return 'ending';} var hw = helloWorldGenerator(); 上面代码定义了一个 Generator 函数 helloWorldGenerator,它内部有两个 yield表达式( hello和 world),即该函数有三个状态:hello,world 和 return 语句(结束执行)。        然后,Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象   yield 表达式   由于 Generator 函数返回的遍历器对象,只有调用 next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。 yield表达式就是暂停标志。

(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。

(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。

  (4)如果该函数没有 return语句,则返回的对象的 value属性值为 undefined        下一步,必须调用遍历器对象的 next方法,使得指针移向下一个状态。也就是说,每次调用 next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个 yield表达式(或 return语句)为止。换言之,Generator 函数是分段执行的, yield表达式是暂停执行的标记,而 next方法可以恢复执行。   hw.next() // { value: 'hello', done: false } hw.next() // { value: 'world', done: false } hw.next() // { value: 'ending', done: true } hw.next() // { value: undefined, done: true }

上面代码一共调用了四次next方法。

第一次调用,Generator 函数开始执行,直到遇到第一个yield表达式为止。next方法返回一个对象,它的value属性就是当前yield表达式的值hello,done属性的值false,表示遍历还没有结束。

第二次调用,Generator 函数从上次yield表达式停下的地方,一直执行到下一个yield表达式。next方法返回的对象的value属性就是当前yield表达式的值world,done属性的值false,表示遍历还没有结束。

第三次调用,Generator 函数从上次yield表达式停下的地方,一直执行到return语句(如果没有return语句,就执行到函数结束)。next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined),done属性的值true,表示遍历已经结束。

  第四次调用,此时 Generator 函数已经运行完毕, next方法返回对象的 value属性为 undefined, done属性为 true。以后再调用 next方法,返回的都是这个值。   总结一下,调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的 next方法,就会返回一个有着 value和 done两个属性的对象。 value属性表示当前的内部状态的值,是 yield表达式后面那个表达式的值; done属性是一个布尔值,表示是否遍历结束。

 

转载于:https://www.cnblogs.com/yfgg/p/10071249.html

相关资源:各显卡算力对照表!

最新回复(0)