前端必刷系列之红宝书——第 6 章

"红宝书" 通常指的是《JavaScript 高级程序设计》,这是一本由 Nicholas C. Zakas(尼古拉斯·扎卡斯)编写的 JavaScript 书籍,是一本广受欢迎的经典之作。这本书是一部翔实的工具书,满满的都是 JavaScript 知识和实用技术。

不管你有没有刷过红宝书,如果现在还没掌握好,那就一起来刷红宝书吧,go!go!go!

系列文章:

第一部分:基本知识(重点、反复阅读)

  1. 前端必刷系列之红宝书------第 1、2 章
  2. 前端必刷系列之红宝书------第 3 章
  3. 前端必刷系列之红宝书------第 4、5 章
  4. 前端必刷系列之红宝书------第 6 章

第 6 章 集合引用类型

Object

对象是一种无序的集合,使用键值对存储数据。键是字符串或符号,值可以是任意类型的数据。

js 复制代码
const myObject = { name: 'John', age: 25, city: 'New York' };
const keysArray = Object.keys(myObject);
// keysArray: ['name', 'age', 'city']

const valuesArray = Object.values(myObject);
// valuesArray: ['John', 25, 'New York']

const entriesArray = Object.entries(myObject);
// entriesArray: [['name', 'John'], ['age', 25], ['city', 'New York']]

const numberOfProperties = Object.keys(myObject).length;
// numberOfProperties: 3

const hasNameProperty = myObject.hasOwnProperty('name'); // true
const hasToStringProperty = myObject.hasOwnProperty('toString'); // false


const target = { a: 1, b: 2 };
const source = { b: 3, c: 4 };
const result = Object.assign(target, source);
// result: { a: 1, b: 3, c: 4 }

// 冻结对象,使其不可修改。冻结的对象不能添加、删除或修改属性。
const myObject = { name: 'John', age: 25 };
Object.freeze(myObject);
// 之后任何修改操作都会失败,如 myObject.name = 'Jane';

// 封闭对象,使其不能添加新属性,但可以修改或删除现有属性。
const myObject = { name: 'John', age: 25 };
Object.seal(myObject);
// 之后不能添加新属性,但可以修改或删除属性

Array

数组是一种有序的集合,可以存储任意类型的值。通过索引访问数组中的元素,数组的长度是动态可变的。

js 复制代码
const arr = [1, 2, 3];
const newLength = arr.push(4, 5);
// arr: [1, 2, 3, 4, 5], newLength: 5

const arr = [1, 2, 3];
const removedElement = arr.pop();
// arr: [1, 2], removedElement: 3

const arr = [2, 3];
const newLength = arr.unshift(0, 1);
// arr: [0, 1, 2, 3], newLength: 4

const arr = [1, 2, 3];
const removedElement = arr.shift();
// arr: [2, 3], removedElement: 1

const arr1 = [1, 2];
const arr2 = [3, 4];
const combinedArray = arr1.concat(arr2);
// combinedArray: [1, 2, 3, 4]

const arr = [1, 2, 3, 4, 5];
const slicedArray = arr.slice(1, 4);
// slicedArray: [2, 3, 4]

const arr = [1, 2, 3, 4, 5];
const removedElements = arr.splice(1, 2, 6, 7);
// arr: [1, 6, 7, 4, 5], removedElements: [2, 3]

const arr = [1, 2, 3, 4, 5];
const index = arr.indexOf(3);
// index: 2

const arr = [1, 2, 3, 4, 3, 5];
const lastIndex = arr.lastIndexOf(3);
// lastIndex: 4

const arr = [1, 2, 3, 4, 5];
const includesElement = arr.includes(3);
// includesElement: true

const arr = ['apple', 'banana', 'orange'];
const result = arr.join(','); // "apple, banana, orange"

const arr = [1, 2, 3, 4];
arr.reverse(); // arr: [4, 3, 2, 1]

const arr = [3, 1, 4, 1, 5, 9, 2];
arr.sort((a, b) => a - b); // arr: [1, 1, 2, 3, 4, 5, 9]

const arr = [1, 2, 3];
arr.forEach((value, index) => {
  console.log(`Element at index ${index}: ${value}`);
});
// 输出:
// Element at index 0: 1
// Element at index 1: 2
// Element at index 2: 3

const arr = [1, 2, 3];
const squaredValues = arr.map(value => value * value);
// squaredValues: [1, 4, 9]

const arr = [1, 2, 3, 4, 5];
const evenNumbers = arr.filter(value => value % 2 === 0);
// evenNumbers: [2, 4]

const arr = [1, 2, 3, 4];
const sum = arr.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
// sum: 10

const arr = [2, 4, 6, 8];
const allEven = arr.every(value => value % 2 === 0);
// allEven: true

const arr = [1, 3, 5, 7];
const hasOdd = arr.some(value => value % 2 !== 0);
// hasOdd: true

const arr = [10, 20, 30, 40];
const index = arr.findIndex(value => value > 25);
// index: 2

const arr = [1, 2, 3, 4];
arr.fill(0, 2); // arr: [1, 2, 0, 0]

const arrayLike = { length: 3, 0: 'a', 1: 'b', 2: 'c' };
const newArray = Array.from(arrayLike);
// newArray: ['a', 'b', 'c']

const newArray = Array.of(1, 'two', 3);
// newArray: [1, 'two', 3]

Array.isArray([1, 2, 3]); // true
Array.isArray('not an array'); // false

定型数组

JavaScript 提供了一种被称为 "TypedArray" 的定型数组,它允许直接操作内存,处理二进制数据,以及在底层使用固定大小的数据类型。TypedArray 是 ECMAScript 6 引入的新特性。

下面是一些常见的 TypedArray 类型:

  1. Int8ArrayUint8ArrayUint8ClampedArray
  • 表示有符号 8 位整数数组、无符号 8 位整数数组、无符号 8 位整数数组(取值范围在 0 到 255 之间,超过边界的值会被截断)。
  1. Int16ArrayUint16Array
  • 表示有符号 16 位整数数组、无符号 16 位整数数组。
  1. Int32ArrayUint32Array
  • 表示有符号 32 位整数数组、无符号 32 位整数数组。
  1. Float32Array
  • 表示 32 位浮点数数组。
  1. Float64Array
  • 表示 64 位双精度浮点数数组。
js 复制代码
// 创建一个 Int32Array,长度为 4
const intArray = new Int32Array(4);

// 设置元素值
intArray[0] = 42;
intArray[1] = 13;
intArray[2] = 7;
intArray[3] = 2023;

// 获取元素值
console.log(intArray[0]); // 42
console.log(intArray[1]); // 13
console.log(intArray[2]); // 7
console.log(intArray[3]); // 2023

TypedArray 提供了一些额外的方法,例如 setsubarray 等,用于更灵活地操作数组的子集和复制。这对于处理二进制数据非常有用,比如处理图像数据、音频数据等。请注意,TypedArray 不同于普通的 JavaScript 数组,因为它们具有固定的长度和元素类型。

Map

Map 是 ES6 引入的集合数据结构,它存储键值对,类似于对象,但键可以是任意数据类型。

与普通的对象相比,Map 有一些优势,其中一些主要的特性包括:

  1. 键的数据类型:
  • Map 中,键可以是任意数据类型,包括原始类型和对象引用。而在普通对象中,键只能是字符串或 Symbol。
  1. 键值对的顺序:
  • Map 会保持键值对的插入顺序。当迭代 Map 时,元素的顺序是按照插入的顺序。
  1. Map 的大小:
  • 通过 size 属性可以轻松获取 Map 的大小,而对象的属性数量需要手动计算。
  1. 内存占用:
  • 固定大小的内存中,Map 大约可以比 Object 多存储 50% 的键值对。
  1. 插入性能:
  • Map 插入新键值对会稍微比 Object 快一点。如果代码涉及大量插入操作,那么 Map 性能更好。
  1. 查找速度:
  • 如果包含少量键值对,Object 有时候速度更快。如果代码涉及大量查找操作,那么某些情况下选择 Object 更好一些。
  1. 删除性能:
  • Map 的 delete() 操作都比插入和查找更快。如果代码涉及大量删除操作,选 Map。
js 复制代码
// 创建一个空的 Map
const myMap = new Map();

// 添加键值对
myMap.set('key1', 'value1');
myMap.set('key2', 'value2');
myMap.set('key3', 'value3');

// 获取值
console.log(myMap.get('key1')); // 输出: value1

// 检查是否包含某个键
console.log(myMap.has('key2')); // 输出: true

// 获取 Map 的大小
console.log(myMap.size); // 输出: 3

// 迭代 Map
myMap.forEach((value, key) => {
  console.log(`${key} = ${value}`);
});

// 删除键值对
myMap.delete('key2');
console.log(myMap.size); // 输出: 2

Map 是一个灵活且强大的数据结构,特别适用于需要使用不同类型的键以及保持插入顺序的场景。

WeakMap

WeakMap 是与 Map 类似的集合类型,但它们对于包含的对象是弱引用,这意味着在其他地方没有引用时,这些对象可以被垃圾回收。

Map 在某些方面有些相似,但有一些关键的区别。

  1. 弱引用键:
  • WeakMap 的键必须是对象,而且是弱引用。这意味着如果没有其他引用指向键,它可能会被垃圾回收。
  1. 不可迭代和无法清空:
  • Map 不同,WeakMap 不提供像 forEach 方法这样的迭代方法,也没有 clear 方法。这是因为键是弱引用的,迭代和清空操作可能导致不确定的行为。
  1. 没有 size 属性:
  • WeakMap 没有类似 Mapsize 属性,因为它不提供直接访问所有键值对的方法。
  1. 不可遍历:
  • 由于没有类似 Mapkeysvaluesentries 方法,WeakMap 不可被直接遍历。这是为了防止泄漏弱引用对象。
js 复制代码
// 创建一个 WeakMap
const myWeakMap = new WeakMap();

// 创建两个对象作为键
const key1 = {};
const key2 = {};

// 向 WeakMap 中添加键值对
myWeakMap.set(key1, 'value1');
myWeakMap.set(key2, 'value2');

// 获取值
console.log(myWeakMap.get(key1)); // 输出: 'value1'

// 检查是否包含某个键
console.log(myWeakMap.has(key2)); // 输出: true

// 删除键值对
myWeakMap.delete(key1);
console.log(myWeakMap.has(key1)); // 输出: false

WeakMap 在某些场景下很有用,特别是在需要关联数据而不希望阻止垃圾回收的情况下。例如,你可以使用 WeakMap 来存储对象的私有数据,而这些数据在对象被销毁时会自动被回收。但请注意,由于 WeakMap 的键是弱引用的,需要谨慎使用,以避免出现不可预测的结果。

Set

Set 是 ES6 引入的集合数据结构,它存储唯一的值,不允许重复。

Array 不同,Set 不是按照插入顺序来保存元素的,而是根据元素的值来保持唯一性。

  1. 元素的唯一性:
  • Set 中的元素必须是唯一的。如果尝试添加已存在的元素,Set 不会进行任何操作。
  1. 无重复值:
  • Set 不允许相同的值存在于集合中。这使得 Set 成为存储唯一值的有序列表的好选择。
  1. 没有键值对:
  • Set 中的元素就是值本身,没有键值对的概念。
js 复制代码
// 创建一个空的 Set
const mySet = new Set();

// 添加元素
mySet.add(1);
mySet.add(2);
mySet.add(3);

// 重复添加相同的元素不会生效
mySet.add(1);

// 检查元素是否存在
console.log(mySet.has(2)); // 输出: true

// 获取 Set 的大小
console.log(mySet.size); // 输出: 3

// 删除元素
mySet.delete(2);

// 遍历 Set
mySet.forEach(value => {
  console.log(value);
});

// 清空 Set
mySet.clear();
console.log(mySet.size); // 输出: 0

Set 是一个非常有用的数据结构,特别适用于需要存储唯一值的场景。在实际应用中,它可以用于去重、存储一组不同的值等。需要注意的是,Set 中的元素比较是使用严格相等运算符(===)进行的,因此在比较对象时要确保引用相同。

WeakSet

WeakSet 是与 Set 类似的集合类型,但它们对于包含的对象是弱引用,这意味着在其他地方没有引用时,这些对象可以被垃圾回收。

  1. 只能包含对象:
  • WeakSet 只能包含对象,而不能包含原始值或其他类型的值。
  1. 弱引用:
  • WeakSet 中的对象是弱引用的,不会阻止这些对象被垃圾回收。
  1. 无法遍历:
  • 由于弱引用的特性,WeakSet 不提供像 Set 那样的遍历方法(比如 forEach)。因此,你不能列出 WeakSet 中的元素。
  1. 没有 size 属性:
  • Set 不同,WeakSet 没有类似 size 的属性,因为你不能获取 WeakSet 中的元素数量。
  1. 没有清空方法:
  • 由于弱引用,WeakSet 没有类似 clear 的方法。
js 复制代码
// 创建一个空的 WeakSet
const myWeakSet = new WeakSet();

// 创建两个对象作为元素
const obj1 = {};
const obj2 = {};

// 添加元素
myWeakSet.add(obj1);
myWeakSet.add(obj2);

// 检查元素是否存在
console.log(myWeakSet.has(obj1)); // 输出: true

// 由于是弱引用,即使将对象赋值为 null,也不会阻止垃圾回收
obj1 = null;

// 检查元素是否存在(由于垃圾回收,应该输出 false)
console.log(myWeakSet.has(obj1)); // 输出: false

WeakSet 主要用于存储对象的弱引用,例如在一些特定的场景中,你希望在其他地方不再引用某个对象时,该对象能够被垃圾回收。

迭代和扩展操作

迭代和扩展操作是 JavaScript 中的一些重要概念,它们涉及到对集合(例如数组、对象、Map、Set 等)的遍历和操作。

js 复制代码
// 用于遍历可迭代对象的元素,例如数组、字符串、Map、Set 等。
const array = [1, 2, 3];
for (const element of array) {
  console.log(element);
}

// 用于遍历对象的可枚举属性。不推荐用于遍历数组。
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
  console.log(key, obj[key]);
}

// 展开数组
const array1 = [1, 2, 3];
const array2 = [...array1, 4, 5];

// 展开对象
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };

// 从类数组对象或可迭代对象创建一个新数组。
const arrayLike = { length: 3, 0: 'a', 1: 'b', 2: 'c' };
const newArray = Array.from(arrayLike);

未完待续...

参考资料

《JavaScript 高级程序设计》(第 4 版)

相关推荐
zqx_712 分钟前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己28 分钟前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称1 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色1 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2341 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河1 小时前
CSS总结
前端·css
NiNg_1_2341 小时前
Vue3 Pinia持久化存储
开发语言·javascript·ecmascript
读心悦2 小时前
如何在 Axios 中封装事件中心EventEmitter
javascript·http
BigYe程普2 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
神之王楠2 小时前
如何通过js加载css和html
javascript·css·html