js三个点“...“省略号的语法
js 三个点 “…” 省略号的语法
概念
“…”是ES6的新语法,该写法在js的不同语境中有不同的解释,可解释为展开语法(Spread syntax)和剩余语法(Rest syntax) ,写法相同,但作⽤却是完全相反的,使⽤时要注意区分
(本⽂主要参考说明编写)
展开语法(Spread syntax)
该语法可简单的理解为浅拷贝,即将对象的⼀层可枚举属性拷贝出来;
官⽅解释:可以在函数调⽤/数组构造时, 将数组表达式或者string在语法层⾯展开;还可以在构造字⾯量对象时, 将对象表达式按key-value 的⽅式展开。( 字⾯量⼀般指 [1, 2, 3] 或者 {name: “mdn”} 这种简洁的构造⽅式)
简单⽰例:
function sum(x, y, z){
js arguments
return x + y + z;
}
const numbers =[1,2,3];
console.log(sum(...numbers));
// output: 6
console.log(sum.apply(null, numbers));
// output: 6
场景语法
函数调⽤:
myFunction(...iterableObj);
字⾯量数组构造或字符串:
[...iterableObj,'4',...'hello',6];
构造字⾯量对象时,进⾏克隆或者属性拷贝(ECMAScript 2018规范新增特性):
let objClone ={...obj };
进阶⽰例
1. 在函数调⽤时使⽤展开语法等价于apply的⽅式
如果想将数组元素迭代为函数参数,⼀般使⽤Function.prototype.apply 的⽅式进⾏调⽤。
function myFunction(x, y, z){}
var args =[0,1,2];
myFunction.apply(null, args);
有了展开语法,可以这样写(所有参数都可以通过展开语法来传值,也不限制多次使⽤展开语法):
function myFunction(x, y, z){}
var args =[0,1,2];
myFunction(...args);
function myFunction(v, w, x, y, z){}
var args =[0,1];
myFunction(-1,...args,2,...[3]);
2. 使⽤ new 关键字来调⽤构造函数时,不能直接使⽤数组+ apply 的⽅式(apply 执⾏的是调⽤ [[Call]] , ⽽不是构造
[[Construct]])。当然, 有了展开语法, 将数组展开为构造函数的参数就很简单了:
var dateFields =[1970,0,1];// 1970年1⽉1⽇
var d =new Date(...dateFields);
3. 没有展开语法的时候,只能组合使⽤ push, splice, concat 等⽅法,来将已有数组元素变成新数组的⼀部分。有了展开语法, 通过字
⾯量⽅式, 构造新数组会变得更简单、更优雅(和参数列表的展开类似, … 在构造字⾯量数组时, 可以在任意位置多次使⽤.):
var parts =['shoulders','knees'];
var lyrics =['head',...parts,'and','toes'];
// ["head", "shoulders", "knees", "and", "toes"]
4. 数组拷贝(copy)
注:实际上, 展开语法和 Object.assign() ⾏为⼀致, 执⾏的都是浅拷贝(只遍历⼀层)。如果想对多维数组进⾏深拷贝, 下⾯的⽰例就有些问题了。
var arr =[1,2,3];
var arr2 =[...arr];// like arr.slice()
arr2.push(4);
// arr2 此时变成 [1, 2, 3, 4]
// arr 不受影响
var a =[[1],[2],[3]];
var b =[...a];
b.shift().shift();// 1
// 此时a数组也会受到影响: [[2], [3]]
5. 连接多个数组
var arr1 =[0,1,2];
var arr2 =[3,4,5];
// 将 arr2 中所有元素附加到 arr1 后⾯并返回
var arr3 = at(arr2);
使⽤展开语法:
var arr1 =[0,1,2];
var arr2 =[3,4,5];
var arr3 =[...arr1,...arr2];
Array.unshift ⽅法常⽤于在数组的开头插⼊新元素/数组. 不使⽤展开语法, ⽰例如下:
var arr1 =[0,1,2];
var arr2 =[3,4,5];
// 将 arr2 中的元素插⼊到 arr1 的开头
Array.prototype.unshift.apply(arr1, arr2)// arr1 现在是 [3, 4, 5, 0, 1, 2]
如果使⽤展开语法, 代码如下: [请注意, 这⾥使⽤展开语法创建了⼀个新的 arr1 数组, Array.unshift ⽅法则是修改了原本存在的 arr1 数组]:
var arr1 =[0,1,2];
var arr2 =[3,4,5];
arr1 =[...arr2,...arr1];// arr1 现在为 [3, 4, 5, 0, 1, 2]
6. 构造字⾯量对象时使⽤展开语法
其⾏为是, 将已有对象的所有可枚举(enumerable)属性拷贝到新构造的对象中.
浅拷贝(Shallow-cloning, 不包含 prototype) 和对象合并, 可以使⽤更简短的展开语法。⽽不必再使⽤ Object.assign() ⽅式.
var obj1 ={ foo:'bar', x:42};
var obj2 ={ foo:'baz', y:13};
var clonedObj ={...obj1 };
// 克隆后的对象: { foo: "bar", x: 42 }
var mergedObj ={...obj1,...obj2 };
// 合并后的对象: { foo: "baz", x: 42, y: 13 }
注:Object.assign() 函数会触发 setters,⽽展开语法则不会。
6.1 不能替换或者模拟 Object.assign() 函数:
var obj1 ={ foo:'bar', x:42};
var obj2 ={ foo:'baz', y:13};
const merge=(...objects )=>({...objects });
var mergedObj =merge( obj1, obj2);
// Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }
var mergedObj =merge({}, obj1, obj2);
/
/ Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
在这段代码中, 展开操作符(spread operator)并没有按预期的⽅式执⾏: ⽽是先将多个解构变为剩余参数(rest parameter), 然后再将剩余参数展开为字⾯量对象。
注:在函数调⽤时使⽤展开语法,请注意不能超过 JavaScript 引擎限制的最⼤参数个数(65536)。
浏览器版本⽀持
1. Spread in array literals
2. Spread in object literals
3. Spread in function calls
剩余参数
也叫剩余语法(Rest syntax),剩余语法看起来和展开语法完全相同,不同点在于, 剩余参数⽤于解构数组和对象。从某种意义上说,剩余语法与展开语法是相反的:展开语法将数组展开为其中的各个元素,⽽剩余语法则是将多个元素收集起来并“凝聚”为单个元素。
简单⽰例:
function sum(...theArgs){
duce((previous, current)=>{
return previous + current;
});
}
console.log(sum(1,2,3));
// output: 6
console.log(sum(1,2,3,4));
// output: 10
场景语法
function(a, b,...theArgs){
// ...
}
如果函数的最后⼀个命名参数以…为前缀,则它将成为⼀个由剩余参数组成的真数组,其中从0(包括)到theArgs.length(排除)的元素由传递给函数的实际参数提供。
在上⾯的例⼦中,theArgs将收集该函数的第三个参数(因为第⼀个参数被映射到a,⽽第⼆个参数映射到b)和所有后续参数。
剩余参数和 arguments对象的区别
剩余参数和 arguments对象之间的区别主要有三个:
剩余参数只包含那些没有对应形参的实参,⽽ arguments 对象包含了传给函数的所有实参。
arguments对象不是⼀个真正的数组,⽽剩余参数是真正的 Array实例,也就是说你能够在它上⾯直接使⽤所有的数组⽅法,⽐如sort,map,forEach或pop。
arguments对象还有⼀些附加的属性 (如callee属性)。
进阶⽰例
1. 因为theArgs是个数组,所以你可以使⽤length属性得到剩余参数的个数:
function fun1(...theArgs){
alert(theArgs.length);
}
fun1();// 弹出 "0", 因为theArgs没有元素
fun1(5);// 弹出 "1", 因为theArgs只有⼀个元素
fun1(5,6,7);// 弹出 "3", 因为theArgs有三个元素
2. 下例中,剩余参数包含了从第⼆个到最后的所有实参,然后⽤第⼀个实参依次乘以它们:
function multiply(multiplier,...theArgs){
return theArgs.map(function(element){
return multiplier * element;
});
}
var arr =multiply(2,1,2,3);
console.log(arr);// [2, 4, 6]
3. 下例演⽰了你可以在剩余参数上使⽤任意的数组⽅法,⽽arguments对象不可以:
function sortRestArgs(...theArgs){
var sortedArgs = theArgs.sort();
return sortedArgs;
}
alert(sortRestArgs(5,3,7,1));// 弹出 1,3,5,7
function sortArguments(){
var sortedArgs = arguments.sort();
return sortedArgs;// 不会执⾏到这⾥
}
alert(sortArguments(5,3,7,1));// 抛出TypeError异常:arguments.sort is not a function
4. 为了在arguments对象上使⽤Array⽅法,它必须⾸先被转换为⼀个真正的数组。
function sortArguments(){
var args = Array.prototype.slice.call(arguments);
var sortedArgs = args.sort();
return sortedArgs;
}
console.log(sortArguments(5,3,7,1));// shows 1, 3, 5, 7
浏览器版本⽀持

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。