lgwebdream / FE-Interview

🔥🔥🔥 前端面试,独有前端面试题详解,前端面试刷题必备,1000+前端面试真题,Html、Css、JavaScript、Vue、React、Node、TypeScript、Webpack、算法、网络与安全、浏览器
https://lgwebdream.github.io/FE-Interview/
Other
6.82k stars 896 forks source link

Day240:写出输出值并解释为什么? #1059

Open Genzhen opened 3 years ago

Genzhen commented 3 years ago
let a = 1,
  b = 2,
  head = { next: { next: 1 } };
[a, b] = [b, a];
[head.next, head.next.next] = [head.next.next, head.next];
console.log(a, b, head);

每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案 欢迎大家在下方发表自己的优质见解 二维码加载失败可点击 小程序二维码

扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。


一、答案

2 1 {next:1}

二、参考解析

通过解构赋值可以交换两个变量的值,所以 [a,b] = [b,a],但是对象就需要注意下了。

head = { next: { next: 1 } };
[head.next, head.next.next] = [head.next.next, head.next];

注意解构的过程,来分析下 [head.next,head.next.next] = [head.next.next,head.next]

可以这么理解,第一步在右边创建临时变量 [1,{next:1}],然后就是临时数组的一个解构,等同于 [head.next,head.next.next] = [1,{next:1}]

但是这里就需要注意下面的两步了

① 的执行 head.next 的值变为 1 了,这时 head 的值就为 {next:1},head 的原先的值被改变了。

② 再执行的时候,head.next.next 现在已经为 undefined 了,即 head.next 为 1,它不是一个对象。

所以最终的值变为了 {next:1};

三、知识点:解构

解构(destructuring)是一种赋值语法,可从数组中提取元素或从对象中提取属性,将其值赋给对应的变量或另一个对象的属性。解构地目的是简化提取数据的过程,增强代码的可读性。有两种解构语法,分别是数组解构和对象解构,两者的区别在于解构赋值语句的左侧,前者是数组字面量,而后者是对象字面量。

3.1 数组解构

在数组解构时,解构会按顺序作用于数组的元素上,也就是说,变量或对象属性要取谁的值与它所在的位置有关。

[a, b] = [1, 2];
console.log(a, b); // 1 2
[b, a] = [1, 2];
console.log(a, b); // 2 1

在经典的冒泡排序中,会交换两个值的位置,传统的做法是用一个临时变量做中转。而如果用解构的语法,那么就可以省略那个临时变量,并且写法更为简洁。

let a = 1,
  b = 2;
/* 数组解构 */
[a, b] = [b, a];

/* 传统做法 */
let tmp = a;
a = b;
b = tmp;

数组解构还可以有选择性的赋值,只要在数组指定的位置上不提供元素,就能为其省去解构赋值。

[, , c] = [1, 2, 3];
console.log(c); // 3

解构赋值表达式的右侧必须是可迭代对象,否则就会报错。

[a, b] = NaN;
[a, b] = Null;
[a, b] = null;

另外也可以结合扩展运算符

[a, ...rest] = [1, 2, 3];
console.log(a); // 1
console.log(rest); // [2,3]

3.2 对象解构

由于对象的属性没有按顺序排列,所以解构对象只会根据属性的名称是否相同来取值。

({ a, b } = { b: 1, a: 2 });
console.log(a, b); // 2,1

其实等同于

({ a: a, b: b } = { b: 1, a: 2 });

分析下它的过程:

所以匹配同名属性只是为了定位,真正被赋值的是处在属性值位置上的变量或另一个对象的属性。

看个例子就好理解了

({ a: e, b: f } = { b: 1, a: 2 });
console.log(e, b); // 2, 1

对象解构允许出现多个同名属性

({ a: e, a: f } = { b: 1, a: 2 });
console.log(e, f); // 2 2

ES6 允许对象字面量的属性名用表达式定义(即属性名可计算)

let obj = { custName: "yd" },
  attr = "Name";
({ ["cust" + attr]: value } = obj);
console.log(value); // yd

3.3 默认值

数组解构和对象解构都能包含一个可供赋值的默认值。如果是数组解构并且指定位置的元素不存在或其值不存在,那么就会使用默认值。判断元素的值是否存在,只要与 undefined 做全等(===)比较,当结果为真时,表示值不存在。

[a, b = 2] = [1];
console.log(b); // 2
[a, b = 2] = [1, undefined];
console.log(b); // 2
[a, b = 2] = [1, null];
console.log(b); // null
MRDANX commented 3 years ago

3.2 对象解构的 1) 小点第三段代码的 console 打印的变量有误。

原文: ({ a: e, b: f } = { b: 1, a: 2 }); console.log(e, b); // 2, 1

修正: ({ a: e, b: f } = { b: 1, a: 2 }); console.log(e, f); // 2, 1

luuman commented 2 years ago

2 1 {next: 1}