JavaScript 数组、对象、字符串和数字的常用方法总结

0 阅读10分钟

 数组方法

修改原数组的方法

push()        // 末尾添加元素,返回新长度
pop()         // 删除最后一个元素,返回该元素
shift()       // 删除第一个元素,返回该元素
unshift()     // 开头添加元素,返回新长度
splice(从第几位开始截取, 截取的长度, 在切口处添加的新元素, ...)      // 添加/删除/替换元素
sort()        // 排序
reverse()     // 反转数组
fill()        // 填充数组
copyWithin()  // 浅复制数组的一部分到同一数组的另一个位置

不修改原数组的方法

concat(arr)      // 合并数组,返回新数组
slice(start, end)       // 提取部分数组,返回新数组
join()        // 数组元素连接成字符串
toString()    // 数组转字符串
toLocaleString() // 本地化字符串表示

// 迭代方法
forEach()     // 遍历数组
map()         // 映射新数组
filter()      // 过滤数组
reduce()      // 累积计算
reduceRight() // 从右向左累积
some()        // 是否有元素通过测试
every()       // 是否所有元素通过测试
find()        // 查找第一个满足条件的元素
findIndex()   // 查找第一个满足条件的索引
findLast()    // 查找最后一个满足条件的元素
findLastIndex() // 查找最后一个满足条件的索引

// ES6+ 新增
flat()        // 扁平化数组
flatMap()     // 先映射后扁平化
includes()    // 是否包含某个值
keys()        // 返回索引迭代器
values()      // 返回值迭代器
entries()     // 返回键值对迭代器
toReversed()  // 返回反转副本 (ES2023)
toSorted()    // 返回排序副本 (ES2023)
toSpliced()   // 返回拼接副本 (ES2023)
with()        // 返回修改单个元素的副本 (ES2023)

🏷️ 字符串方法

获取/查询

charAt(index)          // 返回指定位置字符
charCodeAt(index)      // 返回字符的 Unicode
codePointAt(index)     // 返回字符的码点
indexOf(search)        // 返回首次出现位置
lastIndexOf(search)    // 返回最后出现位置
search(regexp)         // 搜索正则匹配
match(regexp)          // 返回匹配结果
matchAll(regexp)       // 返回所有匹配迭代器
includes(search)       // 是否包含子串
startsWith(search)     // 是否以指定字符串开头
endsWith(search)       // 是否以指定字符串结尾

修改/操作

concat(str1, str2, ...) // 连接字符串
slice(start, end)      // 提取子串
substring(start, end)  // 提取子串
substr(start, length)  // 提取子串(已弃用)
replace(search, replace) // 替换
replaceAll(search, replace) // 替换所有
toUpperCase()          // 转大写
toLowerCase()          // 转小写
toLocaleUpperCase()    // 本地化大写
toLocaleLowerCase()    // 本地化小写
trim()                // 去除两端空格
trimStart() / trimLeft() // 去除开头空格
trimEnd() / trimRight() // 去除结尾空格
padStart(length, pad)  // 开头填充
padEnd(length, pad)    // 结尾填充
repeat(count)          // 重复字符串
normalize(form)        // Unicode 正规化

分割/转换

split(separator, limit) // 分割为数组
toString()             // 返回字符串
valueOf()              // 返回原始值

🔢 数字方法

Number 实例方法

toFixed(digits)        // 保留指定位小数
toExponential(digits)  // 指数表示法
toPrecision(precision) // 指定精度
toLocaleString([locales[, options]]) // 本地化字符串
toString([radix])      // 转为指定进制字符串
valueOf()              // 返回原始值

Number 静态方法

Number.isNaN(value)    // 是否严格等于 NaN
Number.isFinite(value) // 是否有限数
Number.isInteger(value) // 是否整数
Number.isSafeInteger(value) // 是否安全整数
Number.parseFloat(string) // 解析为浮点数
Number.parseInt(string, radix) // 解析为整数

Math 对象方法

// 基本运算
Math.abs(x)           // 绝对值
Math.sqrt(x)          // 平方根
Math.cbrt(x)          // 立方根
Math.pow(x, y)        // x的y次幂

// 舍入
Math.round(x)         // 四舍五入
Math.floor(x)         // 向下取整
Math.ceil(x)          // 向上取整
Math.trunc(x)         // 去除小数部分
Math.fround(x)        // 最接近的单精度浮点表示

// 最大值/最小值
Math.max(...values)   // 最大值
Math.min(...values)   // 最小值

// 随机数
Math.random()         // 0-1随机数

// 三角函数
Math.sin(x), Math.cos(x), Math.tan(x)
Math.asin(x), Math.acos(x), Math.atan(x)
Math.atan2(y, x)      // y/x 的反正切

// 其他
Math.sign(x)          // 符号函数
Math.exp(x)           // e的x次幂
Math.log(x)           // 自然对数
Math.log10(x)         // 以10为底对数
Math.log2(x)          // 以2为底对数
Math.hypot(...values) // 平方和的平方根
Math.clz32(x)         // 32位二进制前导零个数

🗂️ 对象方法

Object 静态方法

// 创建/复制
Object.create(proto)  // 创建对象
Object.assign(target, ...sources) // 合并对象
Object.fromEntries(iterable) // 键值对数组转对象

// 属性描述符
Object.defineProperty(obj, prop, descriptor)
Object.defineProperties(obj, props)
Object.getOwnPropertyDescriptor(obj, prop)
Object.getOwnPropertyDescriptors(obj)

// 属性操作
Object.keys(obj)      // 返回可枚举属性键名数组
Object.values(obj)    // 返回可枚举属性值数组
Object.entries(obj)   // 返回可枚举属性键值对数组
Object.getOwnPropertyNames(obj) // 返回所有属性键名
Object.getOwnPropertySymbols(obj) // 返回 Symbol 属性

// 原型
Object.getPrototypeOf(obj)
Object.setPrototypeOf(obj, proto)

// 状态判断
Object.is(value1, value2) // 严格相等比较
Object.isExtensible(obj)  // 是否可扩展
Object.isSealed(obj)      // 是否密封
Object.isFrozen(obj)      // 是否冻结

// 状态控制
Object.preventExtensions(obj) // 禁止扩展
Object.seal(obj)           // 密封对象
Object.freeze(obj)         // 冻结对象

// ES13+ 新增
Object.hasOwn(obj, prop)  // 检查自有属性

对象实例方法(通过原型继承)

toString()      // 返回字符串表示
valueOf()       // 返回原始值
hasOwnProperty(prop) // 是否自有属性
isPrototypeOf(object) // 是否在原型链上
propertyIsEnumerable(prop) // 属性是否可枚举
toLocaleString() // 本地化字符串表示

📚 JavaScript 常用方法详解(带示例)

📦 数组方法

修改原数组的方法

// push() - 末尾添加元素
let arr1 = [1, 2];
let length = arr1.push(3, 4);
console.log(arr1); // [1, 2, 3, 4]
console.log(length); // 4

// pop() - 删除最后一个元素
let last = arr1.pop();
console.log(arr1); // [1, 2, 3]
console.log(last); // 4

// shift() - 删除第一个元素
let first = arr1.shift();
console.log(arr1); // [2, 3]
console.log(first); // 1

// unshift() - 开头添加元素
arr1.unshift(0, 1);
console.log(arr1); // [0, 1, 2, 3]

// splice() - 添加/删除/替换元素
let fruits = ['apple', 'banana', 'cherry'];
// 删除:从索引1开始删除1个元素
let removed = fruits.splice(1, 1);
console.log(fruits); // ['apple', 'cherry']
console.log(removed); // ['banana']

// 添加:在索引1处添加元素
fruits.splice(1, 0, 'blueberry');
console.log(fruits); // ['apple', 'blueberry', 'cherry']

// 替换:从索引1开始替换1个元素
fruits.splice(1, 1, 'banana');
console.log(fruits); // ['apple', 'banana', 'cherry']

// sort() - 排序
let numbers = [3, 1, 4, 1, 5];
numbers.sort(); // 默认按字符串排序
console.log(numbers); // [1, 1, 3, 4, 5]

// 数字排序
numbers.sort((a, b) => a - b); // 升序
console.log(numbers); // [1, 1, 3, 4, 5]

// 对象数组排序
let users = [  { name: 'Alice', age: 30 },  { name: 'Bob', age: 25 }];
users.sort((a, b) => a.age - b.age);
console.log(users); // 按年龄升序排序

// reverse() - 反转数组
let arr2 = [1, 2, 3, 4];
arr2.reverse();
console.log(arr2); // [4, 3, 2, 1]

// fill() - 填充数组
let arr3 = new Array(5).fill(0);
console.log(arr3); // [0, 0, 0, 0, 0]

// 指定范围填充
arr3.fill(1, 2, 4);
console.log(arr3); // [0, 0, 1, 1, 0]

// copyWithin() - 复制数组的一部分到同一数组的另一位置
let arr4 = [1, 2, 3, 4, 5];
// 从索引3开始复制到索引0,复制2个元素
arr4.copyWithin(0, 3, 5);
console.log(arr4); // [4, 5, 3, 4, 5]

不修改原数组的方法

// concat() - 合并数组
let arr1 = [1, 2];
let arr2 = [3, 4];
let arr3 = [5, 6];
let merged = arr1.concat(arr2, arr3);
console.log(merged); // [1, 2, 3, 4, 5, 6]

// slice() - 提取部分数组
let arr = [1, 2, 3, 4, 5];
console.log(arr.slice(1, 3)); // [2, 3] (不包括结束索引)
console.log(arr.slice(2));    // [3, 4, 5]
console.log(arr.slice(-2));   // [4, 5] (倒数第2个开始)

// join() - 数组元素连接成字符串
let words = ['Hello', 'World'];
console.log(words.join(' ')); // "Hello World"
console.log(words.join('-')); // "Hello-World"

// toString() - 数组转字符串
console.log([1, 2, 3].toString()); // "1,2,3"

// forEach() - 遍历数组
let arr = [1, 2, 3];
arr.forEach((item, index) => {
  console.log(`索引 ${index}: 值 ${item}`);
});

// map() - 映射新数组
let doubled = arr.map(item => item * 2);
console.log(doubled); // [2, 4, 6]

// filter() - 过滤数组
let evens = arr.filter(item => item % 2 === 0);
console.log(evens); // [2]

// find() - 查找第一个满足条件的元素
let users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];
let user = users.find(u => u.id === 2);
console.log(user); // { id: 2, name: 'Bob' }

// findIndex() - 查找第一个满足条件的索引
let index = users.findIndex(u => u.name === 'Bob');
console.log(index); // 1

// reduce() - 累积计算
let sum = [1, 2, 3, 4, 5].reduce((total, current) => total + current, 0);
console.log(sum); // 15

// 计算对象数组的总和
let cart = [
  { name: 'Apple', price: 10 },
  { name: 'Banana', price: 20 }
];
let total = cart.reduce((sum, item) => sum + item.price, 0);
console.log(total); // 30

// some() - 是否有元素通过测试
let hasEven = [1, 3, 5, 7].some(num => num % 2 === 0);
console.log(hasEven); // false

// every() - 是否所有元素通过测试
let allPositive = [1, 2, 3].every(num => num > 0);
console.log(allPositive); // true

// includes() - 是否包含某个值
let arr5 = [1, 2, 3];
console.log(arr5.includes(2)); // true
console.log(arr5.includes(4)); // false

// flat() - 扁平化数组
let nested = [1, [2, [3, [4]]]];
console.log(nested.flat());      // [1, 2, [3, [4]]]
console.log(nested.flat(2));     // [1, 2, 3, [4]]
console.log(nested.flat(Infinity)); // [1, 2, 3, 4]

// flatMap() - 先映射后扁平化
let arr6 = [1, 2, 3];
let result = arr6.flatMap(x => [x, x * 2]);
console.log(result); // [1, 2, 2, 4, 3, 6]

// ES2023 新增方法
let arr7 = [3, 1, 4, 1, 5];

// toReversed() - 返回反转副本
let reversed = arr7.toReversed();
console.log(arr7);    // [3, 1, 4, 1, 5] (原数组不变)
console.log(reversed); // [5, 1, 4, 1, 3]

// toSorted() - 返回排序副本
let sorted = arr7.toSorted();
console.log(sorted); // [1, 1, 3, 4, 5]

// with() - 返回修改单个元素的副本
let modified = arr7.with(2, 99);
console.log(modified); // [3, 1, 99, 1, 5]

🏷️ 字符串方法

let str = "Hello World! Hello JavaScript!";

// charAt() - 获取指定位置字符
console.log(str.charAt(0)); // "H"
console.log(str.charAt(100)); // "" (空字符串)

// charCodeAt() - 获取字符的 Unicode
console.log(str.charCodeAt(0)); // 72 (H的Unicode)

// includes() - 是否包含子串
console.log(str.includes("World")); // true
console.log(str.includes("world")); // false (区分大小写)

// startsWith() - 是否以指定字符串开头
console.log(str.startsWith("Hello")); // true
console.log(str.startsWith("World")); // false

// endsWith() - 是否以指定字符串结尾
console.log(str.endsWith("!")); // true

// indexOf() - 返回首次出现位置
console.log(str.indexOf("Hello")); // 0
console.log(str.indexOf("Hello", 1)); // 13 (从索引1开始搜索)

// lastIndexOf() - 返回最后出现位置
console.log(str.lastIndexOf("Hello")); // 13

// slice() - 提取子串
console.log(str.slice(0, 5)); // "Hello"
console.log(str.slice(6));    // "World! Hello JavaScript!"
console.log(str.slice(-10));  // "JavaScript!"

// substring() - 提取子串
console.log(str.substring(0, 5)); // "Hello"
console.log(str.substring(6, 11)); // "World"

// split() - 分割字符串为数组
console.log(str.split(" ")); // ["Hello", "World!", "Hello", "JavaScript!"]
console.log(str.split(" ", 2)); // ["Hello", "World!"] (限制2个元素)

// replace() - 替换字符串
console.log(str.replace("Hello", "Hi")); // "Hi World! Hello JavaScript!"
console.log(str.replace(/Hello/g, "Hi")); // "Hi World! Hi JavaScript!"

// replaceAll() - 替换所有匹配项
console.log(str.replaceAll("Hello", "Hi")); // "Hi World! Hi JavaScript!"

// toUpperCase() - 转大写
console.log("hello".toUpperCase()); // "HELLO"

// toLowerCase() - 转小写
console.log("HELLO".toLowerCase()); // "hello"

// trim() - 去除两端空格
console.log("  hello world  ".trim()); // "hello world"

// padStart() - 开头填充
console.log("5".padStart(3, "0")); // "005"

// padEnd() - 结尾填充
console.log("5".padEnd(3, "*")); // "5**"

// repeat() - 重复字符串
console.log("ha".repeat(3)); // "hahaha"

// match() - 正则匹配
let email = "test@example.com";
let match = email.match(/^(.+)@(.+)$/);
console.log(match); 
// ["test@example.com", "test", "example.com", index: 0, input: "test@example.com"]

// matchAll() - 匹配所有
let text = "test1@example.com, test2@example.com";
let matches = [...text.matchAll(/\b\w+@\w+.\w+\b/g)];
matches.forEach(m => console.log(m[0]));

// search() - 搜索匹配位置
console.log(str.search("World")); // 6
console.log(str.search(/[A-Z]/)); // 0 (第一个大写字母位置)

// concat() - 连接字符串
console.log("Hello".concat(" ", "World")); // "Hello World"

// valueOf() - 返回原始值
let strObj = new String("Hello");
console.log(strObj.valueOf()); // "Hello"

🔢 数字方法

// Number 实例方法
let num = 123.456789;

// toFixed() - 保留指定位小数
console.log(num.toFixed(2)); // "123.46"
console.log(num.toFixed(0)); // "123"

// toExponential() - 指数表示法
console.log(num.toExponential(2)); // "1.23e+2"

// toPrecision() - 指定精度
console.log(num.toPrecision(4)); // "123.5"

// toLocaleString() - 本地化字符串
console.log(num.toLocaleString('zh-CN')); // "123.457" (中文格式)
console.log(num.toLocaleString('en-US', { 
  style: 'currency', 
  currency: 'USD' 
})); // "$123.46"

// toString() - 转为字符串
console.log(num.toString()); // "123.456789"
console.log((10).toString(2)); // "1010" (二进制)
console.log((255).toString(16)); // "ff" (十六进制)

// Number 静态方法
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("NaN")); // false (字符串不是NaN)

console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite(123)); // true

console.log(Number.isInteger(123)); // true
console.log(Number.isInteger(123.456)); // false

console.log(Number.isSafeInteger(9007199254740991)); // true
console.log(Number.isSafeInteger(9007199254740992)); // false

console.log(Number.parseFloat("123.45px")); // 123.45
console.log(Number.parseInt("1010", 2)); // 10 (二进制转十进制)

// Math 对象方法
console.log(Math.abs(-5)); // 5
console.log(Math.sqrt(16)); // 4
console.log(Math.pow(2, 3)); // 8
console.log(Math.round(4.5)); // 5
console.log(Math.floor(4.9)); // 4
console.log(Math.ceil(4.1)); // 5
console.log(Math.trunc(4.9)); // 4 (去掉小数部分)
console.log(Math.max(1, 3, 2, 5)); // 5
console.log(Math.min(1, 3, 2, 5)); // 1
console.log(Math.random()); // 0-1之间的随机数

// 生成指定范围随机整数
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandomInt(1, 10));

console.log(Math.sign(-5)); // -1
console.log(Math.sign(0)); // 0
console.log(Math.sign(5)); // 1

// 三角函数
console.log(Math.sin(Math.PI / 2)); // 1
console.log(Math.cos(Math.PI)); // -1
console.log(Math.tan(Math.PI / 4)); // 0.9999999999999999

// 对数
console.log(Math.log(Math.E)); // 1
console.log(Math.log10(100)); // 2
console.log(Math.log2(8)); // 3

// 其他
console.log(Math.hypot(3, 4)); // 5 (3² + 4²的平方根)
console.log(Math.clz32(1)); // 31 (32位二进制表示中前导零的个数)

🗂️ 对象方法

let person = {
  name: 'Alice',
  age: 30,
  city: 'New York'
};

// Object.keys() - 获取所有键名
console.log(Object.keys(person)); // ['name', 'age', 'city']

// Object.values() - 获取所有值
console.log(Object.values(person)); // ['Alice', 30, 'New York']

// Object.entries() - 获取所有键值对
console.log(Object.entries(person)); 
// [['name', 'Alice'], ['age', 30], ['city', 'New York']]

// Object.assign() - 合并对象
let obj1 = { a: 1 };
let obj2 = { b: 2 };
let obj3 = { c: 3 };
let merged = Object.assign({}, obj1, obj2, obj3);
console.log(merged); // { a: 1, b: 2, c: 3 }

// 对象浅拷贝
let original = { a: 1, b: { c: 2 } };
let copy = Object.assign({}, original);
original.b.c = 99;
console.log(copy.b.c); // 99 (浅拷贝,嵌套对象受影响)

// Object.create() - 创建对象
let animal = {
  eat() {
    console.log('Eating...');
  }
};
let dog = Object.create(animal);
dog.name = 'Buddy';
dog.eat(); // "Eating..."

// Object.defineProperty() - 定义属性
let obj = {};
Object.defineProperty(obj, 'readOnly', {
  value: 42,
  writable: false,     // 不可写
  enumerable: true,    // 可枚举
  configurable: false  // 不可配置
});
console.log(obj.readOnly); // 42
// obj.readOnly = 99; // 严格模式下会报错

// Object.getOwnPropertyDescriptor() - 获取属性描述符
let descriptor = Object.getOwnPropertyDescriptor(obj, 'readOnly');
console.log(descriptor);

// Object.freeze() - 冻结对象
let frozen = { name: 'Alice' };
Object.freeze(frozen);
// frozen.name = 'Bob'; // 严格模式下会报错
// frozen.age = 30;     // 严格模式下会报错
console.log(Object.isFrozen(frozen)); // true

// Object.seal() - 密封对象
let sealed = { name: 'Alice' };
Object.seal(sealed);
sealed.name = 'Bob'; // 允许修改现有属性
// sealed.age = 30;  // 不允许添加新属性
console.log(Object.isSealed(sealed)); // true

// Object.fromEntries() - 键值对数组转对象
let entries = [['name', 'Alice'], ['age', 30]];
let newObj = Object.fromEntries(entries);
console.log(newObj); // { name: 'Alice', age: 30 }

// Object.hasOwn() - 检查自有属性 (ES2022)
console.log(Object.hasOwn(person, 'name')); // true
console.log(Object.hasOwn(person, 'toString')); // false (继承属性)

// 替代以前的 hasOwnProperty()
console.log(person.hasOwnProperty('name')); // true

// Object.getPrototypeOf() - 获取原型
let arr = [];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true

// Object.setPrototypeOf() - 设置原型
let proto = { greet() { console.log('Hello!'); } };
let obj = {};
Object.setPrototypeOf(obj, proto);
obj.greet(); // "Hello!"

// Object.is() - 严格相等比较
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(0, -0));    // false
console.log(Object.is({}, {}));   // false

🎯 实用示例

1. 数组去重

// 方法1: Set
let arr = [1, 2, 2, 3, 3, 4];
let unique1 = [...new Set(arr)];
console.log(unique1); // [1, 2, 3, 4]

// 方法2: filter
let unique2 = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(unique2); // [1, 2, 3, 4]

// 方法3: reduce
let unique3 = arr.reduce((acc, cur) => {
  if (!acc.includes(cur)) acc.push(cur);
  return acc;
}, []);

2. 对象深拷贝

// 简单深拷贝(仅适用于 JSON 安全数据)
function deepCloneSimple(obj) {
  return JSON.parse(JSON.stringify(obj));
}

// 递归深拷贝
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  
  if (Array.isArray(obj)) {
    return obj.map(item => deepClone(item));
  }
  
  let cloned = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloned[key] = deepClone(obj[key]);
    }
  }
  return cloned;
}

// 使用现代 API
let obj = { a: 1, b: { c: 2 } };
let cloned = structuredClone(obj); // 现代浏览器支持

3. 数组分组

let users = [
  { name: 'Alice', age: 20 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 20 }
];

// 按年龄分组
let grouped = users.reduce((acc, user) => {
  let key = user.age;
  if (!acc[key]) acc[key] = [];
  acc[key].push(user);
  return acc;
}, {});

console.log(grouped);
// {
//   20: [{name: 'Alice', age: 20}, {name: 'Charlie', age: 20}],
//   25: [{name: 'Bob', age: 25}]
// }

4. 防抖节流函数

// 防抖:多次触发只执行最后一次
function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

// 节流:一段时间内只执行一次
function throttle(fn, delay) {
  let lastTime = 0;
  return function(...args) {
    let now = Date.now();
    if (now - lastTime >= delay) {
      fn.apply(this, args);
      lastTime = now;
    }
  };
}

5. 数据格式化

// 数字千分位格式化
function formatNumber(num) {
  return num.toLocaleString('en-US');
}
console.log(formatNumber(1234567.89)); // "1,234,567.89"

// 货币格式化
function formatCurrency(amount, currency = 'USD') {
  return amount.toLocaleString('en-US', {
    style: 'currency',
    currency: currency
  });
}
console.log(formatCurrency(1234.56)); // "$1,234.56"

// 日期格式化
let date = new Date();
console.log(date.toLocaleDateString('zh-CN')); // "2024/1/1"
console