Ben*_*Ben 18 javascript ecmascript-6
为什么扩展语法将我的字符串转换为数组?
var v = 'hello';
var [, ...w] = v; // ["e", "l", "l", "o"]
Run Code Online (Sandbox Code Playgroud)
为什么w不是一个字符串?
Li3*_*357 18
扩展的语法(实际上是一个标点如所指出RobG)允许iterables被扩散成更小的比特.由于字符串是迭代的(它们是内部的字符数组,更具体地说是表示字符的有序整数序列),因此它们可以扩展为单个字符.
接下来,对阵列执行解构分配以对扩展值进行解包和分组.由于你省略了字符数组的第一个元素,并且没有分配引用,它会丢失,并且可迭代对象的其余部分被保存到其中w,扩展到它的各个部分,即字符数组的单个字符.
此操作的特定语义由ECMAcript 2015规范中的ArrayAssignmentPattern:[Elision opt AssignmentRestElement]生产定义:
12.14.5.2运行时语义:DestructuringAssignmentEvaluation
带参数值
[...]
ArrayAssignmentPattern:[Elision opt AssignmentRestElement]
- 让迭代器成为GetIterator(值).
- ReturnIfAbrupt(迭代器).
- 让iteratorRecord为Record {[[iterator]]:iterator,[[done]]:false }.
- 如果有Elision,那么
a.让状态是执行的结果IteratorDestructuringAssignmentEvaluation的省音与iteratorRecord作为参数.
湾 如果状态是突然完成,那么
我.如果iteratorRecord.[[done]]为false,则返回IteratorClose(iterator,status).
II.退货完成(状态).- 我们的结果是执行的结果IteratorDestructuringAssignmentEvaluation的AssignmentRestElement与iteratorRecord作为参数.
- 如果iteratorRecord.[[done]]为false,则返回IteratorClose(迭代器,结果).
- 返回结果.
这里,Elision在使用一个或多个逗号(,)进行传播时引用省略的元素,与名称所暗示的省略音节相当,而AssignmentRestElement指的是将接收传播和解构值的目标,w在本例中.
这样做首先得到对象的迭代器,从内部@@iterator方法和迭代器的步骤,跳过由IteratorDestructuringAssignmentEvaluation中的Elision生成的elision宽度指示的许多元素.完成后,它将逐步完成AssignmentRestElement生成的迭代器,并分配一个包含所有扩展值的新数组 - 就是这样.它接收展开的单字符数组,解压缩以排除第一个字符.w
@@iterator获取迭代的方法是一个众所周知的符号,并且为对象更改它可以改变它的迭代方式,如在Emissary的答案中那样.具体来说,@@iteratorString方法的默认实现如下:
21.1.3.27 String.prototype [@@ iterator]()
当调用@@ iterator方法时,它返回一个Iterator对象(25.1.1.2),该对象迭代String值的代码点,将每个代码点作为String值返回.
因此,迭代器允许迭代单个代码点或字符串的字符 - 因此传播字符串将导致其字符数组.
扩展语法只能应用于可迭代对象.由于String是可迭代的,因此Spread运算符工作正常,并将char数组(String)拆分为char.
您可以使用下面的示例检查,该示例证明String默认是可迭代的.
var s = 'test';
for (k in s) {
console.log(k);
}
Run Code Online (Sandbox Code Playgroud)
ECMAScript6规范甚至提到了这个特定的String情况.
传播运营商
将可迭代集合(如数组
or even a string)的元素传播到文字元素和单个函数参数中.
http://es6-features.org/#SpreadOperator
var str = "foo";
var chars = [ ...str ]; // [ "f", "o", "o" ]
Run Code Online (Sandbox Code Playgroud)
值得一提的是,这是一个特定的情况,只有在使用带扩展运算符的直接String时才会发生.当您在数组中提供单个String时,整个数组将被视为可迭代对象而不是内部的字符串.
var str = [ "hello" ,2 ];
var other = [ ...str ]; // [ "hello" ,2 ]
Run Code Online (Sandbox Code Playgroud)
我知道上面的例子没有多大意义,但只是为了表达在这种情况下String将被区别对待的事实.
在ES2015传播语法是专门作用于内部字符串@@iterator属性-任何对象都可以以这种方式通过分配自己的迭代的迭代器或发电机/function*到obj[Symbol.iterator]财产.
例如,您可以更改新阵列的默认行为...
const a = [...'hello'];
a[Symbol.iterator] = function* (){
for(let i=0; i<this.length; ++i)
yield `${this[i]}!`;
};
console.log([...a]);Run Code Online (Sandbox Code Playgroud)
您也可以更改字符串迭代器,但您必须显式创建String对象.
| 归档时间: |
|
| 查看次数: |
5881 次 |
| 最近记录: |