解构
概念
- 展开语法(Spread syntax), 可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;
- 还可以在构造字面量对象时, 将对象表达式按key-value的方式展开。
- (译者注: 字面量一般指 [1, 2, 3] 或者 {name: “mdn”} 这种简洁的构造方式)
- 来源:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax
解构的时候,变量从左到右一一和元素对齐,可变参数放到变量的最右边
参数解构
function myFn(x,y,z){
console.log(x,y,z)
}
myFn(...[2,3,4])
列表解构
var parts = ["a","c"];
var test1 = ["head",...parts,"tail"];
console.log(test1)
数组解构
-
数据解构,等号左边必须使用中括号[]
-
等号左边变量个数 == 数组元素个数
const arr = [100,200,300];
let [x,y,z] = arr;
console.log(x,y,z)
// 100 200 300
- 等号左边变量个数 < 数组元素个数
- 从左至右一一对应,多余的数组元素舍弃
const arr = [100,200,300];
let [x,y] = arr;
console.log(x,y);
// 100 200
- 等号左边变量个数 > 数组元素个数
- 多余变量返回undefined
const arr = [100,200,300];
let [x,y,z,a,b] = arr;
console.log(x,y,z,a,b);
// 100 200 300 undefined undefined
- 等号左边使用丢弃变量
- JS中,丢弃变量不用写,使用逗号间隔即可
const arr = [100,200,300];
let [,y,,a] = arr;
console.log(y,a);
// 300 undefined
- 可变变量(剩余变量)
- 可变变量必须放在最后,参考函数参数
- 可变变量将收集到的元素封装成数组
const arr = [100,200,300];
let [x,...y] = arr;
console.log(x,y); // 返回100 [200,300]
// 可变变量必须放在最后
// [...y,x] = arr // SyntaxError: Rest element must be last element
- 支持默认值
- 变量对应上等号右边的元素,则返回此元素
- 否则,有默认值返回默认值,没有默认值,返回undefined
const arr = [100,200,300,400,500];
const [x=1,,,,y,z=600] = arr
console.log(x,y,z)
- 易错点
const arr = [100,200,300,400,500];
// const a,b,c = arr // SyntaxError
// e,f,d = arr; // ReferenceError
var a,b,c = arr; // var定义可以悬空,不带分号有时候会出错
let x,y,z = arr; // let定义可以悬空
[e,f,d] = arr;
console.log(a,b,c); // undefined undefined [ 100, 200, 300, 400, 500 ]
console.log(x,y,z);
console.log(e,f,d);
// 常量定义不能悬空,必须定义成功指向一个对象
// const a,b,c -- 逗号表达式,返回最后一个变量c,即c = arr,而变量a和b悬空,抛异常
能对应到数据就返回数据;对应不到数据,变量有默认值返回默认值,无默认值则返回undefined
对象解构
- 对象解构时,需要提供对象的属性名
- 根据属性名找到对应的值,返回对应的值
- 没有找到对应的值,属性有缺省值返回缺省值,无缺省值返回undefined
const obj = {
a:100,
b:200,
c:300
};
var {x,y,z} = obj;
console.log(x,y,z); // undefined undefined undefined
var {a,b,c} = obj;
console.log(a,b,c); // 100 200 300
var {a,b,y=400} = obj;
console.log(a,b,y); // 100 200 400
- 支持别名
- 应用场景:常量定义中,一个标识符只能出现一次,使用别名
const obj = {
a:100,
b:200,
c:300
};
const {a:x,b,d:z="test"} = obj;
console.log(x,b,z); // 有别名必须使用别名,无别名使用原名
// 100 200 test
复杂解构
- 嵌套数组
const arr = [1,[2,3],4];
// 等号左边的数据结构不对应等号右边的数据解构
const [x,y,z] = arr;
console.log(x,y,z); // 1 [ 2, 3 ] 4
// 等号左边的数据结构对应等号右边的数据解构,一一对应
const [a,[b,c],d] = arr;
console.log(a,b,c,d); // 1 2 3 4
const [e,f] = arr;
console.log(e,f); // 1 [ 2, 3 ]
const [g,h,i,j=18] = arr;
console.log(g,h,i,j) // 1 [ 2, 3 ] 4 18
const [k,...l] = arr;
console.log(k,l) // 1 [ [ 2, 3 ], 4 ]
- 对象
var data = {
a:100,
b:[
{
c:200,
d:[],
a:300
},
{
c:1200,
d:[1],
a:130
}
],
c:500
};
console.log(data);
// 注意:等号两边数据结构一致
var {a,b:[{a:m},{a:n}]} = data; // b:[]为对应数据结构,{a:m}为别名
console.log(a,m,n); // 100,300,130
操作
数组的操作
方法 | 描述 |
---|---|
push(…items) | 尾部增加多个元素,返回元素增加后的数组长度 |
pop | 移出最后一个元素,并返回这个元素 |
map | 引入处理函数来处理数组中的每一个元素,返回新的数组 |
filter | 引入处理函数来处理数组中的每一个元素,处理函数返回true的元素保留,否则元素被过滤,保留的元素封装成新的数组返回 |
foreach | 迭代所有元素,无返回值 |
- push、pop
const arr = [1,2,3,4,5];
console.log(arr,arr.push(6,10)); // [ 1, 2, 3, 4, 5, 6,10 ] 7
// 从左至右依次执行,全部执行完毕才打印,索引arr为[ 1, 2, 3, 4, 5, 6,7 ]
// 注意,不是执行一个就打印一个
console.log(arr,arr.pop()) // [ 1, 2, 3, 4, 5, 6 ] 10
- map(callbackfn: (value: T, index: number, array: T[])=> U, thisArg: any)
- callbackfn,程序员自己写,callbackfn (第一参数value返回值,第二参数index返回索引,第三参数array返回数组本身) {return推荐数组}
- 处理后的元素个数不会发生变化,参考Python的map
const arr = [1,2,3,4,5];
m = arr.map((x) => x+1);
m1 = arr.map((x) => [x+1,x+2]);
m2 = arr.map((x,y,z) => {console.log(x,y,z)});
console.log(m) // [ 2, 3, 4, 5, 6 ]
console.log(m1) // [ [ 2, 3 ], [ 3, 4 ], [ 4, 5 ], [ 5, 6 ], [ 6, 7 ] ]
console.log(m2) // [ undefined, undefined, undefined, undefined, undefined ]
- filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any)
- callbackfn,程序员自己写,callbackfn (第一参数value返回值,第二参数index返回索引,第三参数array返回数组本身) {return推荐数组}
- 处理后的元素个数不变或者减少,参考Python的filter
const arr = [1,2,3,4,5];
f = arr.filter((x) => {return (x & 1) == 0;})
f1 = arr.filter((x) => {(x & 1) == 0;}) // 每次迭代,返回undefined,等价false,所有没有结果
console.log(f) // [2,4]
console.log(f1) // []
- forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any)
- callbackfn,程序员自己写,callbackfn (第一参数value返回值,第二参数index返回索引,第三参数array返回数组本身) {无返回值}
const arr = [1,2,3,4,5];
//
f = arr.forEach((x) => {console.log(x);y = x+1;return y})
console.log(f)
/* 返回结果,等效for...of循环遍历打印
1
2
3
4
5
undefined 回调函数中,return语句不起作用,无返回值 */
// 应用
let target = new Array()
arr.forEach((x) => {target.push(x**2)})
console.log(target)
数组练习 – 需要考虑性能
-
有一个数组
const arr = [1,2,3,4,5];
,算出所有元素平均值,且输出平方值是偶数且大于10的平方值 -
方法一
- 先计算,后判断偶数、是否大于10,效率较低
const arr = [1,2,3,4,5];
var target = arr.map(x => x*x).filter(
(x) => {if (x > 10 && (x & 1) == 0){return x}}
)
console.log(target)
- 方法二
- 先判断偶数、是否大于10,后计算
const arr = [1,2,3,4,5];
var s = Math.sqrt(10); // 大于10的开方值,才能通过
var target = [];
arr.forEach((x) => {
if (x > s && (x & 1) == 0){
target.push(x * x)
}
})
console.log(target)
对象的操作
Object的静态方法 | 描述 |
---|---|
Object.keys(obj) | ES5开始支持;返回所有key |
Object.values(obj) | 返回所有的value,实验阶段,支持较差 |
Object.entries(obj) | 返回所有的key_value,实验阶段,支持较差 |
Object.assign(target,…sources) | 使用多个source对象,来填充target对象,返回target对象 |
const obj = {
a:100,
b:200,
c:300
};
console.log(Object.keys(obj)); // [ 'a', 'b', 'c' ]
console.log(Object.values(obj)); // [ 100, 200, 300 ]
console.log(Object.entries(obj)); // [ [ 'a', 100 ], [ 'b', 200 ], [ 'c', 300 ] ]
var ass_obj = Object.assign(
{},
obj,
{a:1000,b:2000},//覆盖target中的a、b属性对应的值
{c:'abc'}, /* 覆盖 */
{c:3000,d:"python"} /* 有则覆盖,无则追加 */
);
console.log(ass_obj);