- symbol 是什么?
- Itertor是什么?
-
symbol的内置符号symbol.Iterator,有什么用?
-
为什么会出现for..of?
-
for..of怎么用?
首先symbol是es6新增的类型,它是一个基本类型,symbol英文翻译是符号的意思。
在叙述symbol之前,推出一个概念,“以操作目标为程序本身的行为特性的编程,我们称为元编程。”
我们已知symbol是es6新增类型,按照逻辑推演:作为新增的类型,symbol一定是为了弥补了之前的不足,所以才出现的,是这样的吗?
首先我们说说它的特别之处:
- symbol属性值对应的值是唯一的,这解决了命名冲突的问题,类似于id的作用。
- symbol值不能与其他数据进行计算,包括与字符串拼接。
- for/in ,for/of遍历时不会遍布symbol属性
这样看是不是觉得没什么特别的?最多也就弥补了命名冲突的问题。
下面推出第二个问题:
Iterotor是什么?
Iterator是一个遍历器的接口,是部署在数据结构上的,很多数据结构原生具备Iterator接口,这就意味着,我们不需要任何处理就可以使用for/of了,拥有symbol.Iterator属性返回的对象,都会在使用for/of时被当作Iterator接口当这个对象符合Iterator接口的标准时,for/of就可以完成任务,不符合就会报错!
刨除这个问题,我们知道symbol可以作为属性值存在。并且它具有唯一的特性,举个栗子:直接let s = Symbol();
测试s
就是Symbol
类型了。怎么说他是唯一的呢?let s = Symbol(); let ss = Symbol(); s == ss
; 结果是false;
或者let s = Symbol('a'); let ss = Symbol('a'); s == ss
; 结果是false
有人会好奇Symbol('a')
里面的参数a又是怎么回事呢?字符串a表示一种修饰,对你当前创建的Symbol
类型的一种修饰,作为区分使用,否则当你创建多个Symbol
数据时,容易混淆。
现在我们回过头说Iterotor是symbol的内置符号,而字符串a是自定义的符号。
symbol的内置符号symbol.Iterator,有什么用?
这个符号可以是任意对象上的一个专门属性,语言机制会自动的在这个属性上寻找一个方法,这个方法会构造一个迭代器来迭代这个对象的值,这个方法就是next方法,...展开和for/of循环会自动使用它,我们可以自定义symbol.iterator属性为任意对象值定义自己的迭代器逻辑,他将覆盖默认的迭代器。相当于是定义了一种元编程行为,提供给Javascript其他部分(也就是运算符和循环结构)在处理定义的对象时使用。
- 在Js中迭代器对象实现了可迭代协议,迭代器对象由Symbol.iterator属性的值返回。
- Symbol.iterator属性的值是一个函数,它返回一个迭代器对象。
- 迭代器指的是拥有next方法的对象。
- 该next方法必须返回一个带有value和done的对象。
为什么会出现for..of?
为了理解条件语句,我们曾想象JavaScript解释器在源代码中会经过不同路径。而循环语句则是把这些路径弯曲又折回起点,以重复执行代码中的某部分。
es6定义了一个新循环语句:for/of。这种新循环虽然使用for关键字,但它们是完全不一同的两种循环,你说和for/in像不像?为什么?
for/of循环是专门用于可迭代对象的,什么是可迭代对象呢?
我们前文提到具有symbol.iterator属性的对象就是可以迭代的。而这个对象就是可迭代对象。
对象本身默认是不可迭代的。运行时尝试对常规对象使用for/of会抛出TypeError:
let o={x:1,y:2,z:3};
for(let element of o){//抛出TypeError,因为o不是迭代的对象
console.log(element);
}
如果你想迭代对象,可以使用for/in循环,或者基于Object.keys()方法的结果使用for/of:
let o={x:1;y:2,z:3};
let keys="";
for(let k of Object .keys(o)){
keys+=k;
}
console.log(keys) //x y z
/*这是因为Object.keys()返回一个对象属性名的数组,而数组是通过for/of来迭代的。也要注意,这种对象的键的迭代并不是实时的,在循环体内修改o不会影响迭代。如果你不在乎对象的属性,也可以像下面这样迭代每个键对应的值:
*/
let o={x:1;y:2,z:3};
let sum=0;
for(let v of Object .values(0)){
sum+=v;
}
console.log(sum)
//6
如果你即想要对象的属性还想要属性的值,可以基于Object.entries()和解构赋值来使用for/of:
let pairs="";
for(let [k , v] of Object .entries(o)){
pairs+=k + v;
}
console.log(pairs)//x 1 y 2 z 3
Object .entries()返回一个数组的数组,其中每个内部数组表示对象的一个属性的键值对。这里使用解构赋值把这些内部数组分开并且分别把它们的元素赋值给两个变量。
不知大家有没有学会使用for/of 循环。这里请注意字符串按照Unicode码点而不是UTF-16字符迭代的。
for...of语法借鉴自C++、Java、C# 和 Python,作为用来遍历所有数据结构的统一方法。