笔记参考javascript.info中文站


  • Object.keys,values,entries
  • 1. 三种方法
  • 2. 转换对象
  • 解构赋值
  • 1. 数组解构
  • 2. 对象解构
  • 3. 嵌套解构
  • 4. 智能函数参数


Object.keys,values,entries

keysvaluesentries 三种方法并不是映射和集合独有的,普通对象和数组也可以使用这三种方法

1. 三种方法

Map 和 Set 在使用这三种方法时直接 . 调用即可,而普通对象则需要这样使用:Object.keys(obj)

举个例子:

let user = {
  name: "John",
  age: 30
};

// 遍历所有的值
for (let value of Object.values(user)) {
  alert(value); // John, then 30
}

此外,Map 和 Set 在使用这三种方法时会返回可迭代对象,而普通对象返回的是一个数组

const man = {
  name: 'someOne',
  age: 58,
  something: '?',
};

console.log(Object.keys(man)); // [ 'name', 'age', 'something' ]
console.log(Object.values(man)); // [ 'someOne', 58, '?' ]
console.log(Object.entries(man));
// [ [ 'name', 'someOne' ], [ 'age', 58 ], [ 'something', '?' ] ]



2. 转换对象

有些方法如 map() filter(),等对象无法使用,而数组可以使用,这时我们就可以先用 Object.entries() 将对象转化成数组,然后再使用这些方法,最后再用 Object.fromEntries() 方法再转回对象

举个例子:

let prices = {
  banana: 1,
  orange: 2,
  meat: 4,
};

let doublePrices = Object.fromEntries(
  // 将价格转换为数组,将每个键/值对映射为另一对
  // 然后通过 fromEntries 再将结果转换为对象
  Object.entries(prices).map(entry => [entry[0], entry[1] * 2])
);

alert(doublePrices.meat); // 8




解构赋值

对象和数组也可以作为函数的参数被处理,然而更多时候我们不需要整个数组和对象,只需要他们的一部分,这时我们就要用到解构赋值方法

1. 数组解构

我们来直接看一个例子:

// 我们有一个存放了名字和姓氏的数组
let arr = ["John", "Smith"]

// 解构赋值
// 设置 firstName = arr[0]
// 以及 surname = arr[1]
let [firstName, surname] = arr;

alert(firstName); // John
alert(surname);  // Smith

很直观,数组被解构了
还可以与一些返回内容是数组的方法交互,写出的代码可读性非常强:

let [firstName, surname] = "John Smith".split(' ');
alert(firstName); // John
alert(surname);  // Smith

注意,解构的过程并不是破坏性的,原始对象、数组并没有改变

我们还可以用这样的形式跳过不需要的元素:

let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
// 跳过第二个元素

有时我们不会将数组的所有内容一一解构,可能会剩下很多,这时就可以用 ... 来进行归纳:

let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

// rest 是包含从第三项开始的其余数组项的数组
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2

变量前加 ... 就可以把后面所有的元素添加到这个数组里,不用一一解构。

我们也可以给左侧的值赋默认值,如果右侧的数组没有足够的元素,那就会赋 undefined ,如果有那就赋数组的对应的值

let [firstName, surname] = [];

alert(firstName); // undefined

// 默认值
let [name = "Guest", surname = "Anonymous"] = ["Julius"];

alert(name);    // Julius(来自数组的值)
alert(surname); // Anonymous(默认值被使用了)

事实上,数组解构的本质就是将数组对应索引的值赋值给另一个变量,逐个进行这样的操作,最终将数组化解成几个独立的变量供调用

//下面两种写法等价

// let [firstName, surname] = arr;
let firstName = arr[0];
let surname = arr[1];



2. 对象解构

对象也可以进行解构:

let options = {
  title: "Menu",
  width: 100,
  height: 200
};

let {height, width, title} = options;

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200

可以将值赋值给对应键名的同名变量中,完成解构

同样的,对象解构也有默认值,默认值的赋予和普通对象属性的赋予格式一样,使用冒号语法

但是,所谓的 “键名” 有可能并不存在,对一个不存在的键用冒号赋予默认值是无效的,打印出来是 undefined,那么对于这种可能缺失的属性,我们可以使用等号语法,此时赋予的默认值不会被抹除

举个例子:

/*冒号语法*/
let options = {
  title: "Menu",
  width: 100,
  height: 200
};

// { sourceProperty: targetVariable }
let {width: w, height: h, title} = options;

alert(title);  // Menu
alert(w);      // 100
alert(h);      // 200
/*等号语法*/
let options = {
  title: "Menu"
};

let {width = 100, height = 200, title} = options;

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200

此外,对象解构同样有剩余模式,剩余的部分由一个对象表示:

let options = {
  title: "Menu",
  height: 200,
  width: 100
};

// title = 名为 title 的属性
// rest = 存有剩余属性的对象
let {title, ...rest} = options;

// 现在 title="Menu", rest={height: 200, width: 100}



3. 嵌套解构

一个对象或数组中嵌套了其他的对象或数组,那就需要嵌套结构,实际上就是数组解构和对象解构的混合应用,对准属性或索引号即可:

let options = {
  size: {
    width: 100,
    height: 200
  },
  items: ["Cake", "Donut"],
  extra: true
};

// 为了清晰起见,解构赋值语句被写成多行的形式
let {
  size: { // 把 size 赋值到这里
    width,
    height
  },
  items: [item1, item2], // 把 items 赋值到这里
  title = "Menu" // 在对象中不存在(使用默认值)
} = options;

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200
alert(item1);  // Cake
alert(item2);  // Donut



4. 智能函数参数

上面说的解构还可以用来解决函数的参数问题:

有些函数的参数数量和种类非常多,记住这些参数很困难,尤其是没有很好的注释时,即使我们记住了也写对了,很多时候我们也需要大量的 undefined 来表示使用默认值的参数,这样会导致函数的可读性很低,而解构可以很好的解决这个问题

也就是用一个对象来表示参数的参数,需要改的参数就写进对象,不改的就不写,在函数的声明处就将参数部分写成解构的形式,这样一来调用函数时就会很简单,可读性也会提高

举个例子:

let options = {
  title: "My menu",
  items: ["Item1", "Item2"]
};

// ……然后函数马上把对象解构成变量
function showMenu({title = "Untitled", width = 200, height = 100, items = []}) {
  // title, items – 提取于 options,
  // width, height – 使用默认值
  alert( `${title} ${width} ${height}` ); // My Menu 200 100
  alert( items ); // Item1, Item2
}

showMenu(options);

这样的写法需要大量编写经验,否则很多时候等我们想起来这回事,这部分代码或许已经写完上交好几天了