“红宝书” 通常指的是《JavaScript 高级程序设计》,这是一本由 Nicholas C. Zakas(尼古拉斯·扎卡斯)编写的 JavaScript 书籍,是一本广受欢迎的经典之作。这本书是一部翔实的工具书,满满的都是 JavaScript 知识和实用技术。
不管你有没有刷过红宝书,如果现在还没掌握好,那就一起来刷红宝书吧,go!go!go!
系列文章:
第一部分:基本知识(重点、反复阅读)
第 6 章 集合引用类型
Object
对象是一种无序的集合,使用键值对存储数据。键是字符串或符号,值可以是任意类型的数据。
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
数组是一种有序的集合,可以存储任意类型的值。通过索引访问数组中的元素,数组的长度是动态可变的。
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 类型:
Int8Array
、Uint8Array
、Uint8ClampedArray
:
- 表示有符号 8 位整数数组、无符号 8 位整数数组、无符号 8 位整数数组(取值范围在 0 到 255 之间,超过边界的值会被截断)。
Int16Array
、Uint16Array
:
- 表示有符号 16 位整数数组、无符号 16 位整数数组。
Int32Array
、Uint32Array
:
- 表示有符号 32 位整数数组、无符号 32 位整数数组。
Float32Array
:
- 表示 32 位浮点数数组。
Float64Array
:
- 表示 64 位双精度浮点数数组。
// 创建一个 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 提供了一些额外的方法,例如 set
、subarray
等,用于更灵活地操作数组的子集和复制。这对于处理二进制数据非常有用,比如处理图像数据、音频数据等。请注意,TypedArray 不同于普通的 JavaScript 数组,因为它们具有固定的长度和元素类型。
Map
Map
是 ES6 引入的集合数据结构,它存储键值对,类似于对象,但键可以是任意数据类型。
与普通的对象相比,Map
有一些优势,其中一些主要的特性包括:
- 键的数据类型:
- 在
Map
中,键可以是任意数据类型,包括原始类型和对象引用。而在普通对象中,键只能是字符串或 Symbol。
- 键值对的顺序:
Map
会保持键值对的插入顺序。当迭代Map
时,元素的顺序是按照插入的顺序。
- Map 的大小:
- 通过
size
属性可以轻松获取Map
的大小,而对象的属性数量需要手动计算。
- 内存占用:
- 固定大小的内存中,Map 大约可以比 Object 多存储 50% 的键值对。
- 插入性能:
- Map 插入新键值对会稍微比 Object 快一点。如果代码涉及大量插入操作,那么 Map 性能更好。
- 查找速度:
- 如果包含少量键值对,Object 有时候速度更快。如果代码涉及大量查找操作,那么某些情况下选择 Object 更好一些。
- 删除性能:
- Map 的 delete() 操作都比插入和查找更快。如果代码涉及大量删除操作,选 Map。
// 创建一个空的 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
在某些方面有些相似,但有一些关键的区别。
- 弱引用键:
WeakMap
的键必须是对象,而且是弱引用。这意味着如果没有其他引用指向键,它可能会被垃圾回收。
- 不可迭代和无法清空:
- 与
Map
不同,WeakMap
不提供像forEach
方法这样的迭代方法,也没有clear
方法。这是因为键是弱引用的,迭代和清空操作可能导致不确定的行为。
- 没有 size 属性:
WeakMap
没有类似Map
的size
属性,因为它不提供直接访问所有键值对的方法。
- 不可遍历:
- 由于没有类似
Map
的keys
、values
和entries
方法,WeakMap
不可被直接遍历。这是为了防止泄漏弱引用对象。
// 创建一个 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
不是按照插入顺序来保存元素的,而是根据元素的值来保持唯一性。
- 元素的唯一性:
Set
中的元素必须是唯一的。如果尝试添加已存在的元素,Set
不会进行任何操作。
- 无重复值:
Set
不允许相同的值存在于集合中。这使得Set
成为存储唯一值的有序列表的好选择。
- 没有键值对:
Set
中的元素就是值本身,没有键值对的概念。
// 创建一个空的 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
类似的集合类型,但它们对于包含的对象是弱引用,这意味着在其他地方没有引用时,这些对象可以被垃圾回收。
- 只能包含对象:
WeakSet
只能包含对象,而不能包含原始值或其他类型的值。
- 弱引用:
WeakSet
中的对象是弱引用的,不会阻止这些对象被垃圾回收。
- 无法遍历:
- 由于弱引用的特性,
WeakSet
不提供像Set
那样的遍历方法(比如forEach
)。因此,你不能列出WeakSet
中的元素。
- 没有 size 属性:
- 与
Set
不同,WeakSet
没有类似size
的属性,因为你不能获取WeakSet
中的元素数量。
- 没有清空方法:
- 由于弱引用,
WeakSet
没有类似clear
的方法。
// 创建一个空的 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 等)的遍历和操作。
// 用于遍历可迭代对象的元素,例如数组、字符串、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 版)
原文链接:https://juejin.cn/post/7325622273107689491 作者:Bigger