js内置对象map,set,generate,iterator
开发中用到最多的场景,父子组件通信,分发事件,组件传值。
1.generate 迭代器
可以暂停和开始
- *function
- yield
- yield*
1.funtion* 定义一个迭代器函数
- generator.prototype.next()
- generator.prototype.return()
- generator.prototype.throw() 抛出错误
1 | function* generator(i) { |
生成器函数有一个next()方法
next()
方法返回一个对象,这个对象包含两个属性:value 和 done,value 属性表示本次 yield
表达式的返回值,done 属性为布尔类型,表示生成器后续是否还有 yield
语句,即生成器函数是否已经执行完毕并返回。
调用 next()
方法时,如果传入了参数,那么这个参数会传给上一条执行的 yield 语句左边的变量,例如下面例子中的x
:
1 | function *gen(){ |
x=yield ‘foo’ 不同于 let x=yield ‘foo’
后者不会将等号右边的赋值给左边
1 | function *createIterator() { |
接收参数(可以多个
1 | function* idMaker(){ |
显示返回
next()的value变为返回的值,done的状态变为true
注意
- 不能当构造器使用
应用
- 使用迭代器遍历二维数组为一维数组、也可以多维转为一维数组
2.yield*
用于委托给另一个generate或者可迭代对象
yield*
表达式本身的值是当迭代器关闭时返回的值(即done
为true
时)。
1 | function* g1() { |
除了生成器对象这一种可迭代对象,yield*
还可以 yield
其它任意的可迭代对象,比如说数组、字符串、arguments
对象等等。
1 | function* g3() { |
3.迭代器Iterator
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator
属性,Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数,其实就是我们上面写的myiteration函数,执行这个函数,就会返回一个带有next方法的遍历器对象。至于属性名Symbol.iterator,它是一个表达式,返回Symbol
对象的iterator
属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内。
在js里原生具备 Iterator 接口的数据结构如下:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象 因此,上面的任意一个数据类型都支持for…of遍历,也可以调用自身的
2.判断类型
- Object.prototype.toString.call(args)
- instanceof
- typeof
- constructor
工具函数判断 isEmpty
1.Object.prototype.toString.call(args)
1 | Object.prototype.toString.call('') ; // [object String] |
2.instanceof
instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。 在这里需要特别注意的是:instanceof 检测的是原型,我们用一段伪代码来模拟其内部执行过程:
instanceof 只能用来判断两个对象是否属于实例关系****, 而不能判断一个对象实例具体属于哪种类型。
3.typeof
缺点:对象之间无法细分
1 | typeof` `''``; ``// string 有效 |
- 对于基本类型,除 null 以外,均可以返回正确的结果。
- 对于引用类型,除 function 以外,一律返回 object 类型。
- 对于 null ,返回 object 类型。
- 对于 function 返回 function 类型。
4.constructor
定义变量的时候都隐式的调用了new关键字
null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。
函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object
因此,为了规范开发,在重写对象原型时一般都需要重新给 constructor 赋值,以保证对象实例的类型不被篡改。
特殊判定
- 判定数组 Array.isArray()
- 判断 null 和 underfinded isNull , isUnderfinded
- 判断空数组 JSON.stringify(obj) === ‘[]’
Array.isArray()
3.map
Map
对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者基本类型)都可以作为一个键或一个值。
属性
- size (无length属性,容易踩坑)
方法
- clear()
- delete()
- entries()
- forEach
- get()
- has()
- keys()
- set()
- values()
set与object对比
一个 Object
的键必须是一个 String
或是 Symbol
。
一个 Map
的键可以是任意值,包括函数、对象或任意基本类型。
一个 Object
有一个原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
Map
默认情况不包含任何键。只包含显式插入的键。
虽然 Object
的键目前是有序的,但并不总是这样,而且这个顺序是复杂的。因此,最好不要依赖属性的顺序。
Map
中的键是有序的。
Object
的键值对个数只能手动计算。
Map
的键值对个数可以轻易地通过 size
属性获取。
JavaSctipt 的 for…of 表达式并不能直接迭代对象。for of 配合 Object.keys()
Map
是 可迭代的 的,所以可以直接被迭代。
Set在频繁增删键值对的场景下表现更好。
1.values()
values()
方法返回一个新的迭代器对象。它包含按顺序插入 Map
对象中每个元素的 value
值
2.keys
keys()
返回一个引用的迭代器对象。它包含按照顺序插入 Map
对象中每个元素的 key 值。
1 | const map1 = new Map(); |
理解:作用类似于对象的Object.keys() 但它的实现方式(返回的是迭代器),对象返回的是数组
3.entries
entries()
方法返回一个新的迭代器对象,其中包含 Map
对象中按插入顺序排列的每个元素的 [key, value]
对。在这种情况下,这个迭代器对象也是一个可迭代对象,因此可以使用 for-of 循环。当使用 [Symbol.iterator]
时,它返回一个函数,该函数在调用时返回迭代器本身。
1 | const map1 = new Map(); |
4.set()
设置值,如果存在值将被覆盖
4.set
属性
- size (无length属性,容易踩坑)
方法
- clear()
- delete()
- entries()
- forEach
- values()
- has()
- keys()
1.keys()
返回迭代器对象,迭代的为key
2.values()
返回迭代器对象,迭代的为value
3.entries()
entries()
方法返回一个新的迭代器对象,这个对象包含的元素是类似 [value, value]
形式的数组,value
是集合对象中的每个元素,迭代器对象元素的顺序即集合对象中元素插入的顺序。由于集合对象不像 Map
对象那样拥有 key
,然而,为了与 Map
对象的 API 形式保持一致,故使得每一个条目的 key 和 value 都拥有相同的值,因而最终返回一个 [value, value]
形式的数组。
1 | const set1 = new Set(); |
**console.log(iterator1.next()) **
此处返回的迭代器对象,使用gen.next()打印,值会打印出两次
4.add()
1 | const set1 = new Set(); |
参考
思考
js中的接口指的是什么
接口:抽象对象,也具有方法
此处实现功能:生成一个数组之后,定义一个迭代器函数,当调用for of的时候,调用之前定义的迭代器函数