Blob

Blob

Blob

在JavaScript中,Blob(Binary Large Object)是一个用于表示不可变二进制数据的对象。它通常用于处理文件、图片、音频、视频等二进制内容,也可以用于在客户端生成文件并触发下载。

1. 创建 Blob

你可以通过 Blob 构造函数创建一个 Blob 对象。构造函数接受两个参数:

  • parts:一个数组,包含需要组合成 Blob 的数据。数据可以是字符串、ArrayBuffer、BufferSource 或其他 Blob 对象。
  • options:一个可选对象,用于指定 Blob 的类型(type)和其他属性。

示例:

1
2
3
4
const text = "Hello, world!";
const blob = new Blob([text], { type: "text/plain" });
console.log(blob.size); // 输出 Blob 的大小
console.log(blob.type); // 输出 Blob 的 MIME 类型

如果你需要创建一个图片文件:

1
const imageBlob = new Blob([arrayBufferData], { type: "image/png" });

2. 使用 Blob

Blob 对象通常用于以下场景:

a. 文件下载

你可以通过创建一个 URL 并触发下载来使用 Blob:

1
2
3
4
5
6
7
const blob = new Blob(["Hello, world!"], { type: "text/plain" });
const url = URL.createObjectURL(blob); // 创建一个指向 Blob 的 URL
const a = document.createElement("a");
a.href = url;
a.download = "hello.txt";
a.click();
URL.revokeObjectURL(url); // 释放 URL

b. 文件上传

在前端,你可以将 Blob 对象放入 FormData 中,然后通过 AJAX 上传到服务器:

1
2
3
4
5
6
const formData = new FormData();
formData.append("file", blob, "filename.txt");
fetch("https://example.com/upload", {
method: "POST",
body: formData
});

c. 读取 Blob 数据

如果你需要读取 Blob 的内容,可以使用 FileReader

1
2
3
4
5
const reader = new FileReader();
reader.onload = function (event) {
console.log(event.target.result); // 输出 Blob 的内容
};
reader.readAsText(blob); // 读取 Blob 为文本

3. Blob 的特点

  • 不可变:Blob 对象是不可变的,一旦创建,其内容不能被修改。
  • 灵活:可以包含多种类型的数据,支持多种 MIME 类型。
  • 高效:适合处理大文件,因为它不会将整个文件内容加载到内存中。

4. 与 File 的关系

FileBlob 的一个子类,专门用于表示文件系统中的文件。File 对象继承了 Blob 的所有属性和方法,并额外添加了 namelastModified 属性。

示例:

1
2
3
4
5
const fileInput = document.querySelector("input[type='file']");
fileInput.addEventListener("change", function (event) {
const file = event.target.files[0];
console.log(file instanceof Blob); // true
});

总结

Blob 是一个非常强大的工具,用于处理二进制数据和文件操作。它在前端开发中非常常用,尤其是在文件上传、下载、图片处理等场景中。

Boolean

Boolean

Boolean 里有什么

1
2
3
4
5
6
console.log(Object.getOwnPropertyNames(Boolean))
console.log(Object.getOwnPropertyNames(Boolean.prototype))
console.log(Object.getOwnPropertyNames(new Boolean()))
['length', 'name', 'prototype']
['constructor', 'toString', 'valueOf']
[]

Boolean

在 JavaScript 中,Boolean 对象是一个包装对象,用于将布尔值包装成对象。它提供了对布尔值的操作和转换等功能。以下是关于 Boolean 对象的详细介绍:
一、创建 Boolean 对象

  1. 使用构造函数
    • 可以通过 Boolean() 构造函数来创建一个 Boolean 对象。例如:
      1
      2
      let boolObj = new Boolean(true);
      let boolObj2 = new Boolean();//false
      这里 boolObj 就是一个 Boolean 对象,它的值是 true。如果传入的参数可以转换为布尔值 true,那么创建的 Boolean 对象的值就是 true;如果传入的参数可以转换为布尔值 false,那么创建的 Boolean 对象的值就是 false。例如:
      1
      2
      let boolObj1 = new Boolean(0); // 值为 false
      let boolObj2 = new Boolean("Hello"); // 值为 true
      因为在 JavaScript 中,0、空字符串 ""nullundefinedNaN 等被认为是“假值”,会被转换为布尔值 false;而其他值(如非零数字、非空字符串等)会被转换为布尔值 true
  2. 直接量语法(不推荐用于创建对象)
    • 通常我们使用 truefalse 这两个布尔直接量来表示布尔值。虽然也可以用 Boolean(true)Boolean(false) 这种方式来获取布尔值,但这不是创建 Boolean 对象的语法,而是返回一个布尔原始值。例如:
      1
      let boolValue = Boolean(true); // boolValue 是一个布尔原始值,值为 true
      这种方式只是进行类型转换,而不是创建对象。

二、Boolean 对象的属性和方法

  1. 属性
    • Boolean.prototype:这是所有 Boolean 对象的原型。它允许你向所有的 Boolean 实例添加属性和方法。例如:
      1
      2
      3
      4
      5
      Boolean.prototype.sayHello = function() {
      return "Hello";
      };
      let myBool = new Boolean(true);
      console.log(myBool.sayHello()); // 输出 "Hello"
      这里我们给 Boolean 对象的原型添加了一个 sayHello 方法,然后通过 Boolean 对象实例 myBool 调用了这个方法。
    • Boolean.length:这个属性表示 Boolean 构造函数接受的参数数量。对于 Boolean 构造函数来说,它的值是 1,因为 Boolean 构造函数最多接受一个参数。
  2. 方法
    • Boolean.toString():这个方法返回一个表示布尔值的字符串。例如:
      1
      2
      let boolObj = new Boolean(true);
      console.log(boolObj.toString()); // 输出 "true"
      如果 Boolean 对象的值是 true,那么 toString() 方法返回字符串 "true";如果值是 false,则返回字符串 "false"
    • Boolean.valueOf():这个方法返回 Boolean 对象的实际布尔值。例如:
      1
      2
      let boolObj = new Boolean(false);
      console.log(boolObj.valueOf()); // 输出 false
      这个方法在需要获取 Boolean 对象的原始布尔值时非常有用,比如在逻辑运算中。

三、使用场景和注意事项

  1. 使用场景
    • 在需要将布尔值包装成对象以便利用对象的特性(如添加方法等)时,可以使用 Boolean 对象。例如,在一些复杂的逻辑处理中,你可能需要对布尔值进行封装,并为其添加一些额外的操作方法。
    • 在进行类型检查和转换时,Boolean 对象也可以发挥作用。比如,你可以通过 Boolean() 构造函数来将其他类型的数据转换为布尔值,以便进行条件判断等操作。
  2. 注意事项
    • 由于 Boolean 对象是一个对象,所以在进行布尔运算时,它的行为可能和布尔原始值不同。例如:
      1
      2
      3
      4
      let boolObj = new Boolean(false);
      if (boolObj) {
      console.log("This will be printed");
      }
      在这个例子中,即使 boolObj 的值是 false,条件判断 if (boolObj) 也会为 true,因为 boolObj 是一个对象,而对象在布尔上下文中会被视为 true。所以,在进行布尔逻辑判断时,通常推荐使用布尔原始值,而不是 Boolean 对象。

js操作时间

Js操作时间

在JavaScript中,操作时间通常涉及到Date对象的使用。Date对象可以用来获取当前日期和时间,以及进行日期和时间的格式化、计算等操作。以下是一些常见的日期和时间操作方法:

获取当前日期和时间

1
2
const now = new Date();
console.log(now); // 输出当前日期和时间

获取日期和时间的各个部分

1
2
3
4
5
6
7
8
9
const now = new Date();
console.log(now.getFullYear()); // 获取年份
console.log(now.getMonth() + 1); // 获取月份(0-11,0表示1月)
console.log(now.getDate()); // 获取日期(1-31)
console.log(now.getDay()); // 获取星期几(0-6,0表示周日)
console.log(now.getHours()); // 获取小时(0-23)
console.log(now.getMinutes()); // 获取分钟(0-59)
console.log(now.getSeconds()); // 获取秒(0-59)
console.log(now.getMilliseconds()); // 获取毫秒(0-999)

设置日期和时间

1
2
3
4
5
6
7
8
const now = new Date();
now.setFullYear(2025); // 设置年份
now.setMonth(0); // 设置月份(0-11,0表示1月)
now.setDate(1); // 设置日期(1-31)
now.setHours(12); // 设置小时(0-23)
now.setMinutes(0); // 设置分钟(0-59)
now.setSeconds(0); // 设置秒(0-59)
now.setMilliseconds(0); // 设置毫秒(0-999)

日期和时间的格式化

JavaScript原生没有提供直接的日期格式化函数,但可以使用toLocaleString()方法进行简单的格式化,或者使用第三方库如date-fnsmoment.js进行更复杂的格式化。

1
2
3
4
const now = new Date();
console.log(now.toLocaleString()); // 默认格式
console.log(now.toLocaleDateString()); // 仅日期
console.log(now.toLocaleTimeString()); // 仅时间

计算日期和时间的差值

1
2
3
4
const start = new Date('2025-01-01');
const end = new Date('2025-01-02');
const diff = end - start; // 差值为毫秒
console.log(diff); // 输出 86400000(一天的毫秒数)

使用第三方库

对于复杂的日期和时间操作,可以使用第三方库如date-fnsmoment.js,这些库提供了更丰富的功能和更简洁的API。

使用date-fns

1
2
3
4
5
import { format, addDays, differenceInDays } from 'date-fns';
const now = new Date();
console.log(format(now, 'yyyy-MM-dd HH:mm:ss')); // 格式化日期
const future = addDays(now, 3); // 三天后的日期
console.log(differenceInDays(future, now)); // 日期差值

使用moment.js

1
2
3
4
5
const moment = require('moment');
const now = moment();
console.log(now.format('YYYY-MM-DD HH:mm:ss')); // 格式化日期
const future = now.add(3, 'days'); // 三天后的日期
console.log(future.diff(now, 'days')); // 日期差值

通过这些方法和工具,可以方便地在JavaScript中进行各种日期和时间的操作和处理.

JSON

JSON

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,但是JSON是独立于语言的文本格式,尽管它的名字中有JavaScript。JSON的结构和JavaScript对象字面量非常相似,但它遵循严格的语法规则,使其成为一种数据交换语言。

JSON的主要特点包括:

  1. 键值对:JSON数据由键值对组成,键和值之间用冒号(:)分隔,键值对之间用逗号(,)分隔。
  2. 数据类型:JSON支持以下数据类型:
    • 字符串(String)
    • 数字(Number)
    • 对象(Object),在JSON中称为对象
    • 数组(Array)
    • 布尔值(Boolean),true和false
    • 空值(null)
  3. 字符串:所有的键和字符串值必须使用双引号(”)。
  4. 数组:在JSON中,数组用方括号([])表示。
  5. 对象:在JSON中,对象用花括号({})表示。
  6. 可读性:JSON的格式清晰、结构化,易于阅读和编写。
  7. 语言无关性:虽然JSON基于JavaScript,但它与JavaScript的特定功能(如函数和对象原型)无关,因此可以被许多不同的编程语言轻松解析和生成。
  8. 广泛使用:JSON在Web开发中被广泛用于前后端之间的数据交换,API响应,配置文件等。

JSON的示例:

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "John Doe",
"age": 30,
"isEmployed": true,
"skills": ["JavaScript", "JSON", "API"],
"address": {
"street": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip": "12345"
}
}

在这个示例中,我们有一个包含多个键值对的对象,其中一些值是基本数据类型,一些是数组,还有一个是嵌套的对象。JSON格式的数据可以被JavaScript轻松解析为对象,也可以被其他支持JSON的编程语言解析为相应的数据结构。

方法

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。在 JavaScript 中,JSON 对象提供了几个方法来处理 JSON 数据,主要包括 stringifyparse 方法。这些方法用于将 JavaScript 对象转换为 JSON 字符串,以及将 JSON 字符串转换为 JavaScript 对象。

1. JSON.stringify()

用途

  • 将 JavaScript 对象或值转换为 JSON 字符串。
    语法
1
JSON.stringify(value, replacer, space)
  • value:要转换的 JavaScript 对象或值。
  • replacer(可选):一个函数,用于在字符串化过程中转换值,或者一个数组,用于指定要包含在字符串化的对象中的属性。
  • space(可选):用于控制结果字符串中的空白字符,用于美化输出。
    示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const obj = {
name: 'Kimi',
age: 25,
hobbies: ['reading', 'coding', 'traveling']
};
// 基本用法
const jsonString = JSON.stringify(obj);
console.log(jsonString);
// 输出: {"name":"Kimi","age":25,"hobbies":["reading","coding","traveling"]}
// 使用 replacer 函数
const jsonStringWithReplacer = JSON.stringify(obj, (key, value) => {
if (key === 'age') {
return undefined; // 排除 age 属性
}
return value;
});
console.log(jsonStringWithReplacer);
// 输出: {"name":"Kimi","hobbies":["reading","coding","traveling"]}
// 使用 space 美化输出
const prettyJsonString = JSON.stringify(obj, null, 2);
console.log(prettyJsonString);
// 输出:
// {
// "name": "Kimi",
// "age": 25,
// "hobbies": [
// "reading",
// "coding",
// "traveling"
// ]
// }

2. JSON.parse()

用途

  • 将 JSON 字符串转换为 JavaScript 对象。
    语法
1
JSON.parse(text, reviver)
  • text:要解析的 JSON 字符串。
  • reviver(可选):一个函数,用于在解析过程中转换结果对象的属性值。
    示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const jsonString = '{"name":"Kimi","age":25,"hobbies":["reading","coding","traveling"]}';
// 基本用法
const obj = JSON.parse(jsonString);
console.log(obj);
// 输出: { name: 'Kimi', age: 25, hobbies: [ 'reading', 'coding', 'traveling' ] }
// 使用 reviver 函数
const objWithReviver = JSON.parse(jsonString, (key, value) => {
if (key === 'age') {
return value + 1; // 将 age 增加 1
}
return value;
});
console.log(objWithReviver);
// 输出: { name: 'Kimi', age: 26, hobbies: [ 'reading', 'coding', 'traveling' ] }

3. toJSON()

用途

  • toJSON 是一个方法,可以在对象上定义,用于自定义对象的 JSON 表示形式。当 JSON.stringify 调用时,会自动调用对象的 toJSON 方法(如果存在)。
    示例
1
2
3
4
5
6
7
8
9
10
const obj = {
name: 'Kimi',
age: 25,
toJSON() {
return { name: this.name };
}
};
const jsonString = JSON.stringify(obj);
console.log(jsonString);
// 输出: {"name":"Kimi"}

总结

  • JSON.stringify():将 JavaScript 对象或值转换为 JSON 字符串。
  • JSON.parse():将 JSON 字符串转换为 JavaScript 对象。
  • toJSON():自定义对象的 JSON 表示形式,用于 JSON.stringify 调用时。
    这些方法在处理 JSON 数据时非常有用,特别是在与服务器进行数据交换时。通过合理使用这些方法,可以轻松地将数据在 JavaScript 对象和 JSON 字符串之间进行转换。

Math

Math

JavaScript的 Math 对象是一个内置对象,它提供了一系列数学常量和函数,用于执行各种数学运算。由于 Math 是一个静态对象,其属性和方法可以直接通过 Math 来访问,而不需要创建实例。

常量

Math对象提供了一些常用的数学常量,例如:

  • Math.PI:圆周率π,约等于3.14159。
  • Math.E:自然对数的底数e,约等于2.718。
  • Math.LN2:2的自然对数,约等于0.693。
  • Math.LN10:10的自然对数,约等于2.302。
  • Math.LOG2E:e的以2为底的对数,约等于1.442。
  • Math.LOG10E:e的以10为底的对数,约等于0.434.
  • Math.SQRT1_2:1/2的平方根,约等于0.707。
  • Math.SQRT2:2的平方根,约等于1.414。

方法

Math对象提供了许多数学运算的方法,以下是一些常用的方法:

  • 四舍五入和取整

    • Math.round(x):四舍五入到最接近的整数。
    • Math.floor(x):向下取整,即取小于或等于x的最大整数。
    • Math.ceil(x):向上取整,即取大于或等于x的最小整数.
    • Math.trunc(x):去除x的小数部分,只保留整数部分。
    • Math.sign(x):返回x的符号,-1表示负数,1表示正数,0表示零,NaN表示非数字。
  • 随机数

    • Math.random():返回一个0到1之间的随机数(包括0,但不包括1)。
  • 三角函数

    • Math.sin(x):返回x的正弦值。
    • Math.cos(x):返回x的余弦值。
    • Math.tan(x):返回x的正切值。
    • Math.asin(x):返回x的反正弦值。
    • Math.acos(x):返回x的反余弦值。
    • Math.atan(x):返回x的反正切值。
    • Math.atan2(y, x):返回从原点到点(x, y)的线段与x轴正方向的夹角的反正切值。
  • 指数和对数

    • Math.exp(x):返回e的x次幂。
    • Math.log(x):返回x的自然对数(以e为底)。
    • Math.log10(x):返回x的以10为底的对数。
    • Math.log2(x):返回x的以2为底的对数.
    • Math.pow(x, y):返回x的y次幂。
  • 平方根和立方根

    • Math.sqrt(x):返回x的平方根。
    • Math.cbrt(x):返回x的立方根。
  • 最大值和最小值

    • Math.max(x, y, z, ...):返回一组数中的最大值。
    • Math.min(x, y, z, ...):返回一组数中的最小值。
  • 其他

    • Math.abs(x):返回x的绝对值。
    • Math.hypot(x, y, z, ...):返回所有参数平方和的平方根,即计算直角三角形的斜边长度。
    • Math.clz32(x):返回x的32位整数形式的前导零的数量。
    • Math.imul(x, y):返回x和y的32位整数乘积。
    • Math.fround(x):返回x的四舍五入到最接近的32位单精度浮点数的值。

示例

1
2
3
4
5
6
7
8
9
console.log(Math.PI); // 输出圆周率π
console.log(Math.round(3.7)); // 输出4
console.log(Math.floor(3.7)); // 输出3
console.log(Math.ceil(3.2)); // 输出4
console.log(Math.random()); // 输出一个0到1之间的随机数
console.log(Math.sin(Math.PI / 2)); // 输出1
console.log(Math.pow(2, 3)); // 输出8
console.log(Math.max(1, 3, 2)); // 输出3
console.log(Math.min(1, 3, 2)); // 输出1

Math对象提供的方法和常量在数学计算和处理数值时非常有用,能够帮助开发者简化代码并提高程序的效率。

Object

js操作object

Object 里有什么

!Object.png

1
2
3
console.log(Object.getOwnPropertyNames(Object))
console.log(Object.getOwnPropertyNames(Object.prototype))
console.log(Object.getOwnPropertyNames(new Object()))

Object 对象自身的属性

1
(26) ['length', 'name', 'prototype', 'assign', 'getOwnPropertyDescriptor', 'getOwnPropertyDescriptors', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'hasOwn', 'is', 'preventExtensions', 'seal', 'create', 'defineProperties', 'defineProperty', 'freeze', 'getPrototypeOf', 'setPrototypeOf', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'entries', 'fromEntries', 'values', 'groupBy']

Object.prototype

1
(12) ['constructor', '__defineGetter__', '__defineSetter__', 'hasOwnProperty', '__lookupGetter__', '__lookupSetter__', 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'valueOf', '__proto__', 'toLocaleString']

在 JavaScript 中,Object 是所有对象的祖先,它本身也具有一些属性和方法。这些属性和方法可以用于操作对象,包括创建对象、获取对象属性、修改对象属性等。以下是一些 Object 对象自身的常用属性和方法:

一、属性

(一)Object.prototype
  • 描述:所有对象都会继承 Object.prototype 上的属性和方法。这是因为 Object 是 JavaScript 中所有对象的原型。例如,hasOwnProperty 方法就是定义在 Object.prototype 上的,所有对象都可以使用这个方法来判断自身是否具有某个特定的属性。
  • 示例
    1
    2
    3
    4
    let obj = { name: "Kimi" };
    console.log(obj.hasOwnProperty("name")); // 输出 true
    console.log(obj.hasOwnProperty("toString")); // 输出 false
    // 因为 toString 是继承自 Object.prototype 的,不是 obj 自身的属性
(二)Object.length
  • 描述Object 对象的 length 属性值为 1。这个属性在实际开发中很少用到,它主要是用于一些 JavaScript 内部的机制,比如函数调用时参数的处理等。
  • 示例
    1
    console.log(Object.length); // 输出 1

二、方法

(一)创建对象相关的方法
  1. Object.create(proto[, propertiesObject])
  • 功能:创建一个新对象,使用现有的对象来提供新创建对象的 __proto__(原型)。
  • 参数
    • proto:新创建对象的原型对象。
    • propertiesObject(可选):一个对象,其自身属性将被定义为新创建对象的属性。
  • 返回值:新创建的对象。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    let protoObj = {
    greet: function() {
    console.log("Hello");
    }
    };
    let newObj = Object.create(protoObj);
    newObj.greet(); // 控制台输出 Hello
  1. Object.assign(target, ...sources)
  • 功能:将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
  • 参数
    • target:目标对象。
    • sources:源对象。
  • 返回值:目标对象。
  • 示例
    1
    2
    3
    4
    5
    let target = { a: 1 };
    let source1 = { b: 2 };
    let source2 = { c: 3 };
    Object.assign(target, source1, source2);
    console.log(target); // 输出 { a: 1, b: 2, c: 3 }
(二)获取对象属性相关的方法
  1. Object.getOwnPropertyDescriptor(obj, prop)
  • 功能:返回指定对象上一个自有属性(不是继承属性)的属性描述符。
  • 参数
    • obj:需要检索其属性描述符的对象。
    • prop:需要检索其属性描述符的属性的名称。
  • 返回值:一个对象,描述了给定属性的配置。如果指定的属性不存在于对象上,则返回 undefined
  • 示例
    1
    2
    3
    4
    5
    6
    7
    let obj = {
    name: "Kimi",
    age: 20
    };
    let descriptor = Object.getOwnPropertyDescriptor(obj, "name");
    console.log(descriptor);
    // 输出 { value: "Kimi", writable: true, enumerable: true, configurable: true }
  1. Object.getOwnPropertyDescriptors(obj)
  • 功能:返回一个对象,它包含了指定对象自身的所有属性的属性描述符。
  • 参数obj - 需要检索其属性描述符的对象。
  • 返回值:一个对象,其属性是给定对象的属性名,属性值是对应属性的属性描述符。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let obj = {
    name: "Kimi",
    age: 20
    };
    let descriptors = Object.getOwnPropertyDescriptors(obj);
    console.log(descriptors);
    // 输出 {
    // name: { value: "Kimi", writable: true, enumerable: true, configurable: true },
    // age: { value: 20, writable: true, enumerable: true, configurable: true }
    // }
  1. Object.keys(obj)
  • 功能:返回一个由给定对象的自身可枚举属性组成的数组。
  • 参数obj - 需要返回其键名的对象。
  • 返回值:一个数组,其元素是字符串,表示给定对象的键名。
  • 示例
    1
    2
    3
    4
    5
    let obj = {
    name: "Kimi",
    age: 20
    };
    console.log(Object.keys(obj)); // 输出 [ 'name', 'age' ]
  1. Object.values(obj)
  • 功能:返回一个给定对象自身可枚举属性的值的数组。
  • 参数obj - 需要返回其键值的对象。
  • 返回值:一个数组,其元素是给定对象的键值。
  • 示例
    1
    2
    3
    4
    5
    let obj = {
    name: "Kimi",
    age: 20
    };
    console.log(Object.values(obj)); // 输出 [ 'Kimi', 20 ]
  1. Object.entries(obj)
  • 功能:返回一个给定对象自身可枚举属性的键值对的数组。
  • 参数obj - 需要返回其键值对的对象。
  • 返回值:一个数组,其元素是 [key, value] 形式的数组,表示给定对象的键值对。
  • 示例
    1
    2
    3
    4
    5
    let obj = {
    name: "Kimi",
    age: 20
    };
    console.log(Object.entries(obj)); // 输出 [ [ 'name', 'Kimi' ], [ 'age', 20 ] ]
(三)修改对象属性相关的方法
  1. Object.defineProperty(obj, prop, descriptor)
  • 功能:在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
  • 参数
    • obj:要在其上定义属性的对象。
    • prop:要定义或修改的属性的名称。
    • descriptor:将被定义或修改的属性的描述符。
  • 返回值:被定义或修改属性的对象。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let obj = {};
    Object.defineProperty(obj, "name", {
    value: "Kimi",
    writable: false, // 设置为只读
    enumerable: true,
    configurable: true
    });
    console.log(obj.name); // 输出 Kimi
    obj.name = "Moonshot"; // 由于 writable 为 false,这行代码不会改变 obj.name 的值
    console.log(obj.name); // 仍然输出 Kimi
  1. Object.defineProperties(obj, props)
  • 功能:在一个对象上定义多个新属性,或者修改多个现有属性,并返回该对象。
  • 参数
    • obj:要在其上定义属性的对象。
    • props:一个对象,其自身属性指定了要在 obj 上定义或修改的属性。
  • 返回值:被定义或修改属性的对象。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    let obj = {};
    Object.defineProperties(obj, {
    name: {
    value: "Kimi",
    writable: true
    },
    age: {
    value: 20,
    writable: false
    }
    });
    console.log(obj.name); // 输出 Kimi
    console.log(obj.age); // 输出 20
    obj.age = 21; // 由于 age 的 writable 为 false,这行代码不会改变 obj.age 的值
    console.log(obj.age); // 仍然输出 20
(四)其他方法
  1. Object.is(value1, value2)
  • 功能:判断两个值是否相同。这个方法比严格相等运算符(===)更严格,能够区分 -0+0,并且认为 NaNNaN 是相等的。
  • 参数
    • value1:第一个要比较的值。
    • value2:第二个要比较的值。
  • 返回值:如果两个值相同,返回 true;否则返回 false
  • 示例
    1
    2
    3
    console.log(Object.is(0, -0)); // 输出 false
    console.log(Object.is(NaN, NaN)); // 输出 true
    console.log(Object.is(1, 1)); // 输出 true
  1. Object.seal(obj)
  • 功能:封闭一个对象,阻止添加新的属性并将所有现有属性标记为不可配置。被封闭的对象仍然可以更改其属性的值。
  • 参数obj - 要封闭的对象。
  • 返回值:被封闭的对象。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    let obj = {
    name: "Kimi"
    };
    Object.seal(obj);
    obj.age = 20; // 这行代码不会添加 age 属性
    console.log(obj); // 输出 { name: "Kimi" }
    obj.name = "Moonshot"; // 可以修改属性值
    console.log(obj); // 输出 { name: "Moonshot" }
    1. Object.freeze(obj)
  • 功能:冻结一个对象。冻结指的是不能向这个对象添加新的属性,不能删除已有属性,不能修改已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。也就是说,这个对象永远不变。
  • 参数obj - 要冻结的对象。
  • 返回值:被冻结的对象。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    let obj = {
    name: "Kimi"
    };
    Object.freeze(obj);
    obj.age = 20; // 这行代码不会添加 age 属性
    console.log(obj); // 输出 { name: "Kimi" }
    obj.name = "Moonshot"; // 由于对象被冻结,这行代码不会改变 name 的值
    console.log(obj); // 仍然输出 { name: "Kimi" }

Object.prototype 的属性

Object.prototype 是 JavaScript 中所有对象的原型,它提供了一些基本的方法和属性,这些方法和属性会被所有对象继承。以下是一些 Object.prototype 上的常用属性和方法:

一、属性

(一)constructor
  • 描述:指向创建该对象的构造函数。这个属性可以用来判断对象是由哪个构造函数创建的。
  • 示例
    1
    2
    3
    4
    5
    6
    let obj = new Object();
    console.log(obj.constructor === Object); // 输出 true
    let arr = new Array();
    console.log(arr.constructor === Array); // 输出 true
    let func = new Function();
    console.log(func.constructor === Function); // 输出 true

二、方法

(一)hasOwnProperty(prop)
  • 功能:判断对象自身是否具有指定的属性,不考虑继承的属性。
  • 参数prop - 要检查的属性名称。
  • 返回值:如果对象自身具有指定的属性,返回 true;否则返回 false
  • 示例
    1
    2
    3
    4
    5
    let obj = {
    name: "Kimi"
    };
    console.log(obj.hasOwnProperty("name")); // 输出 true
    console.log(obj.hasOwnProperty("toString")); // 输出 false
(二)isPrototypeOf(object)
  • 功能:判断当前对象是否是另一个对象的原型。
  • 参数object - 要检查的对象。
  • 返回值:如果是当前对象是另一个对象的原型,返回 true;否则返回 false
  • 示例
    1
    2
    3
    let protoObj = {};
    let obj = Object.create(protoObj);
    console.log(protoObj.isPrototypeOf(obj)); // 输出 true
(三)propertyIsEnumerable(prop)
  • 功能:判断对象自身指定的属性是否可枚举。
  • 参数prop - 要检查的属性名称。
  • 返回值:如果对象自身指定的属性可枚举,返回 true;否则返回 false
  • 示例
    1
    2
    3
    4
    5
    let obj = {
    name: "Kimi"
    };
    console.log(obj.propertyIsEnumerable("name")); // 输出 true
    console.log(obj.propertyIsEnumerable("toString")); // 输出 false
(四)toLocaleString()
  • 功能:返回对象的本地字符串表示。这个方法通常会被 toString 方法调用。
  • 返回值:对象的本地字符串表示。
  • 示例
    1
    2
    3
    4
    5
    let obj = {
    name: "Kimi",
    age: 20
    };
    console.log(obj.toLocaleString()); // 输出 [object Object]
(五)toString()
  • 功能:返回对象的字符串表示。这个方法经常被用来获取对象的类型信息。
  • 返回值:对象的字符串表示。
  • 示例
    1
    2
    3
    4
    5
    6
    let obj = new Object();
    console.log(obj.toString()); // 输出 [object Object]
    let arr = new Array();
    console.log(arr.toString()); // 输出 [object Array]
    let func = new Function();
    console.log(func.toString()); // 输出 [object Function]
(六)valueOf()
  • 功能:返回对象的原始值。对于 Object 对象,它返回对象本身。
  • 返回值:对象的原始值。
  • 示例
    1
    2
    let obj = new Object();
    console.log(obj.valueOf() === obj); // 输出 true

三、注意事项

  • 由于所有对象都继承自 Object.prototype,所以在使用对象时,这些方法和属性都是可用的。但是,如果在对象上定义了同名的属性或方法,会覆盖继承自 Object.prototype 的属性或方法。
  • 在进行对象属性检查时,通常使用 hasOwnProperty 方法来区分对象自身的属性和继承的属性。例如,在遍历对象属性时,如果只关心对象自身的属性,可以结合 for...in 循环和 hasOwnProperty 方法使用:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    let obj = {
    name: "Kimi",
    age: 20
    };
    for (let prop in obj) {
    if (obj.hasOwnProperty(prop)) {
    console.log(prop); // 输出 name 和 age
    }
    }
    这样可以避免遍历到继承自 Object.prototype 的属性。

Object

在 JavaScript 中,操作对象是常见的任务之一。对象是一种键值对的集合,可以用来存储和组织数据。以下是一些基本的操作对象的方法和示例:

创建对象

使用对象字面量

1
2
3
4
5
const person = {
name: 'Alice',
age: 25,
city: 'New York'
};

使用构造函数 Object()

1
2
3
4
const person = new Object();
person.name = 'Alice';
person.age = 25;
person.city = 'New York';

访问对象属性

使用点符号

1
console.log(person.name); // 输出: Alice

使用方括号

1
console.log(person['age']); // 输出: 25

方括号方式允许使用变量作为属性名,或者访问包含特殊字符的属性名。

修改对象属性

1
person.age = 26; // 修改属性值

添加新属性

1
person.job = 'Engineer'; // 添加新属性

删除属性

1
delete person.city; // 删除属性

检查属性是否存在

使用 in 操作符

1
2
3
if ('name' in person) {
console.log('Name property exists');
}

使用 hasOwnProperty 方法

1
2
3
if (person.hasOwnProperty('age')) {
console.log('Age property exists');
}

遍历对象

使用 for...in 循环

1
2
3
4
5
for (const key in person) {
if (person.hasOwnProperty(key)) {
console.log(key, person[key]);
}
}

for...in 循环会遍历对象的所有可枚举属性,包括继承的属性。使用 hasOwnProperty 可以确保只遍历对象自身的属性.

使用 Object.keys(), Object.values(), Object.entries()

1
2
3
4
5
6
7
8
9
// 获取对象的键数组
const keys = Object.keys(person);
console.log(keys); // ['name', 'age', 'job']
// 获取对象的值数组
const values = Object.values(person);
console.log(values); // ['Alice', 26, 'Engineer']
// 获取对象的键值对数组
const entries = Object.entries(person);
console.log(entries); // [['name', 'Alice'], ['age', 26], ['job', 'Engineer']]

拷贝对象

浅拷贝

1
const personCopy = { ...person }; // 使用展开运算符

展开运算符会创建一个新对象,并将原对象的属性复制到新对象中。注意,这是浅拷贝,对于对象属性中的对象或数组,拷贝的是引用,而不是值.

深拷贝

深拷贝可以通过递归函数或使用第三方库(如 Lodash 的 _.cloneDeep)来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const result = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepCopy(obj[key]);
}
}
return result;
}
const deepPersonCopy = deepCopy(person);

对象解构

1
2
const { name, age } = person;
console.log(name, age); // Alice 26

对象解构允许你从对象中提取多个属性,并将它们赋值给变量。

对象合并

使用对象字面量

1
2
3
4
5
6
7
8
9
const additionalInfo = {
email: 'alice@example.com'
};
const fullPerson = {
...person,
...additionalInfo
};
console.log(fullPerson);
// { name: 'Alice', age: 26, job: 'Engineer', email: 'alice@example.com' }

使用展开运算符可以合并多个对象。如果存在相同的属性,后面的属性值会覆盖前面的属性值.

对象的其他方法

  • Object.assign():用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它返回目标对象.
  • Object.freeze():冻结一个对象,使其不可修改.
  • Object.seal():密封一个对象,使其不可扩展,但属性值仍可修改.
  • Object.is():比较两个值是否严格相等,与 === 类似,但有一些细微差别,例如处理 NaN-0 等.
    这些是 JavaScript 中操作对象的一些常用方法和技巧。掌握它们可以帮助你更高效地处理和组织数据。

prototype和__proto__的区别

在 JavaScript 中,prototype__proto__ 是两个非常重要的概念,它们都与原型链有关,但它们的用途和含义有所不同。以下是对它们的详细区别:

一、定义和用途

(一)prototype

  • 定义prototype 是每个函数(Function)对象都有一个属性。当你使用一个函数作为构造函数来创建对象实例时,这个函数的 prototype 属性指向一个对象,这个对象被称为原型对象(prototype object)。所有通过这个构造函数创建的实例都会共享这个原型对象上的属性和方法。
  • 用途prototype 主要用于定义构造函数的原型对象,以便所有通过该构造函数创建的实例可以共享这些属性和方法。这有助于实现代码复用和节省内存。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function Person(name, age) {
    this.name = name;
    this.age = age;
    }
    Person.prototype.sayHello = function() {
    console.log("Hello, my name is " + this.name);
    };
    let person1 = new Person("Kimi", 20);
    let person2 = new Person("Moonshot", 30);
    person1.sayHello(); // 控制台输出 Hello, my name is Kimi
    person2.sayHello(); // 控制台输出 Hello, my name is Moonshot

(二)__proto__

  • 定义__proto__ 是一个对象实例的属性,它指向该对象的原型对象。这个属性是一个非标准的属性,但在大多数现代浏览器中都支持。它提供了一种方式来访问对象的原型对象。
  • 用途__proto__ 主要用于在运行时访问和修改对象的原型对象。通过 __proto__,你可以查看对象的原型链,或者动态地改变对象的原型。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    let obj = {
    name: "Kimi"
    };
    console.log(obj.__proto__); // 输出 Object.prototype
    console.log(obj.__proto__ === Object.prototype); // 输出 true
    // 修改对象的原型
    let protoObj = {
    greet: function() {
    console.log("Hello");
    }
    };
    obj.__proto__ = protoObj;
    obj.greet(); // 控制台输出 Hello

二、访问方式

(一)prototype

  • 访问方式prototype 属性只能通过函数对象访问。例如,Person.prototype
  • 示例
    1
    console.log(Person.prototype); // 输出 { sayHello: [Function: sayHello], constructor: [Function: Person] }

(二)__proto__

  • 访问方式__proto__ 属性通过对象实例访问。例如,obj.__proto__
  • 示例
    1
    console.log(obj.__proto__); // 输出 { constructor: [Function: Object], ... }

三、标准性和兼容性

(一)prototype

  • 标准性prototype 是 ECMAScript 规范中定义的标准属性,是 JavaScript 原型链机制的核心部分。
  • 兼容性prototype 在所有现代 JavaScript 环境中都支持。

(二)__proto__

  • 标准性__proto__ 不是 ECMAScript 规范中定义的标准属性,但它在大多数现代浏览器中都支持。在 ES6 中,推荐使用 Object.getPrototypeOfObject.setPrototypeOf 来替代 __proto__
  • 兼容性:虽然 __proto__ 在大多数现代浏览器中都支持,但在一些严格遵循标准的环境中(如某些 Node.js 环境)可能不推荐使用。推荐使用标准的 Object.getPrototypeOfObject.setPrototypeOf 方法。
  • 示例
    1
    2
    3
    4
    5
    // 获取对象的原型
    console.log(Object.getPrototypeOf(obj)); // 输出 { constructor: [Function: Object], ... }
    // 设置对象的原型
    Object.setPrototypeOf(obj, protoObj);
    obj.greet(); // 控制台输出 Hello

四、总结

  • prototype
    • 定义:函数对象的属性,指向原型对象。
    • 用途:定义构造函数的原型对象,实现代码复用。
    • 访问方式:通过函数对象访问,例如 Person.prototype
    • 标准性:标准属性,广泛支持。
  • __proto__
    • 定义:对象实例的属性,指向该对象的原型对象。
    • 用途:在运行时访问和修改对象的原型对象。
    • 访问方式:通过对象实例访问,例如 obj.__proto__
    • 标准性:非标准属性,推荐使用 Object.getPrototypeOfObject.setPrototypeOf
      理解这些区别有助于更好地使用 JavaScript 的原型链机制,合理地选择使用 prototype 还是 __proto__,以实现更高效和标准的代码。
      prototype和__proto__ 的关系。
      主要有以下三点:
      1)函数(或构造函数)身上才有 prototype (prototype名字叫原型,原型是一个对象);
      2)而其他任何通过构造函数实例化出来的对象(不包括null、undefined)身上都有 __proto____proto__是隐式原型,隐式原型也一个对象)
      3)实例化对象的__proto__ 就是构造函数的 prototype   (=== 关系)
      附:undefind 和 null 既没有prototype也没有 proto  ,因为它俩不是函数,也不是函数实例化出来的对象
1
2
'a'.__proto__ === String.protptype //true
 true.__proto__  ===  Boolean.prototype //true
1
2
3
4
var obj = {}
console.log(obj.__proto__ === Object.prototype);
console.log(obj.constructor === Object);
console.log(Object.getPrototypeOf(obj) === Object.prototype);

getPrototypeOf

Object.getPrototypeOf() 是 JavaScript 中的一个静态方法,用于获取指定对象的原型。以下是关于 Object.getPrototypeOf() 的详细信息:

语法

1
Object.getPrototypeOf(obj)

参数

  • obj:要返回其原型的对象。

返回值

  • 给定对象的原型,可能是 null

示例

使用 getPrototypeOf

1
2
3
const proto = {};
const obj = Object.create(proto);
console.log(Object.getPrototypeOf(obj) === proto); // true

非对象强制类型转换

在 ES5 中,如果 obj 参数不是对象,则会抛出 TypeError 异常。在 ES2015 中,该参数将被强制转换为 Object

1
2
3
4
Object.getPrototypeOf("foo");
// TypeError: "foo" is not an object (ES5 code)
Object.getPrototypeOf("foo");
// String.prototype (ES2015 code)

检查两个对象是否具有相同的原型

1
2
3
4
5
6
// Creating a simple function
let first_var = function myFun() { };
// Creating a object
let second_var = Object.create(first_var);
// Getting the output
console.log(Object.getPrototypeOf(second_var) === first_var); // false

获取函数的原型

1
2
let func1 = function () {};
console.log(Object.getPrototypeOf(func1) === Function.prototype); // true

注意事项

  • Object.getPrototypeOf() 是获取对象原型的标准方法,推荐使用此方法而不是非标准的 __proto__ 属性。
  • 在 ES5 中,如果传入的参数不是对象,会抛出 TypeError 异常。在 ES2015 中,非对象参数会被强制转换为对象。

浏览器兼容性

Object.getPrototypeOf() 方法在现代浏览器中广泛支持,包括 Chrome、Edge、Firefox、Opera 和 Safari。

总结

Object.getPrototypeOf() 是一个非常有用的工具,用于获取对象的原型。它在处理对象继承和属性访问时非常方便,特别是在需要检查对象的原型链时。

判断两个object是否相同

在 JavaScript 中,判断两个对象是否相同是一个常见的需求。由于对象是引用类型,直接使用 ===== 只能比较它们的引用,而不能比较它们的内容。因此,需要通过其他方式来判断两个对象是否具有相同的结构和值。
以下是几种判断两个对象是否相同的方法:

1. 浅比较(Shallow Comparison)

浅比较只检查对象的第一层属性是否相同。如果对象的属性值是基本类型(如字符串、数字等),可以使用以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function shallowEqual(obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (let key of keys1) {
if (obj1[key] !== obj2[key]) {
return false;
}
}
return true;
}
// 示例
const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };
const obj3 = { a: 1, b: 3 };
console.log(shallowEqual(obj1, obj2)); // true
console.log(shallowEqual(obj1, obj3)); // false

缺点:这种方法只能比较对象的第一层属性,无法处理嵌套对象或数组。

2. 深比较(Deep Comparison)

深比较会递归地检查对象的所有属性,包括嵌套对象和数组。可以使用递归函数实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function deepEqual(obj1, obj2) {
if (obj1 === obj2) {
return true;
}
if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
return false;
}
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (let key of keys1) {
if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {
return false;
}
}
return true;
}
// 示例
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
const obj3 = { a: 1, b: { c: 3 } };
console.log(deepEqual(obj1, obj2)); // true
console.log(deepEqual(obj1, obj3)); // false

优点:这种方法可以处理嵌套对象和数组。
缺点:递归实现可能会导致性能问题,尤其是在处理大型对象时。

3. 使用 JSON 序列化

如果对象中没有函数、undefinedNaN 或循环引用,可以使用 JSON.stringify 进行比较:

1
2
3
4
5
6
7
8
9
function objectsEqual(obj1, obj2) {
return JSON.stringify(obj1) === JSON.stringify(obj2);
}
// 示例
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
const obj3 = { a: 1, b: { c: 3 } };
console.log(objectsEqual(obj1, obj2)); // true
console.log(objectsEqual(obj1, obj3)); // false

优点:实现简单,代码简洁。
缺点

  1. 无法处理对象中的函数、undefinedNaN 或循环引用。
  2. 性能较差,因为 JSON.stringify 会递归遍历对象。

4. 使用库

如果需要更可靠的实现,可以使用现成的库,如 Lodash_.isEqual 方法:

1
2
3
4
5
6
import _ from 'lodash';
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
const obj3 = { a: 1, b: { c: 3 } };
console.log(_.isEqual(obj1, obj2)); // true
console.log(_.isEqual(obj1, obj3)); // false

优点_.isEqual 是一个经过优化的深比较方法,可以处理各种复杂情况,包括循环引用、特殊值等。
缺点:需要引入额外的库。

总结

  • 如果只需要比较对象的第一层属性,可以使用浅比较。
  • 如果需要处理嵌套对象和数组,可以实现深比较。
  • 如果对象结构复杂或需要处理特殊值,建议使用现成的库(如 Lodash)。
  • 如果对象结构简单且没有特殊值,可以使用 JSON.stringify 进行比较。
    根据具体需求选择合适的方法即可。

Proxy

Proxy 对象

Proxy 对象是 ECMAScript 6 (ES6) 引入的一种新型对象,它能够拦截和修改对对象的基本操作,如属性访问、赋值和函数调用。以下是 Proxy 对象的一些关键特性和用法:

  1. 基本语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const target = {};
const handler = {
get(target, prop, receiver) {
// 处理 get 操作
console.log(`Getting ${prop}`);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
// 处理 set 操作
console.log(`Setting ${prop} to ${value}`);
return Reflect.set(target, prop, value, receiver);
}
};
const proxy = new Proxy(target, handler);
在这个示例中,我们可以看到 `Proxy` 拦截了 `get` 和 `set` 操作,并在控制台中输出了相关的信息。
  1. 拦截操作: Proxy 可以拦截对象的各种操作,包括但不限于属性访问、赋值、枚举、函数调用等。Handler 对象可以包含多个方法,例如 getPrototypeOfsetPrototypeOfisExtensiblepreventExtensionsgetOwnPropertyDescriptordefinePropertyhasgetsetdeletePropertyownKeysapplyconstruct 等。
  2. 响应式系统中的应用: 在 Vue 3 中,响应式系统的重构使用了 Proxy API,替代了 Vue 2 中的 Object.defineProperty。这一改变提升了性能和可扩展性,使得 Vue 的响应式特性能够处理更多的数据类型。
  3. Vue 3 响应式系统的工作原理
    • 创建响应式对象:在 Vue 3 中,可以通过 reactive API 创建响应式对象。例如:
    1
    2
    3
    4
    import { reactive } from 'vue';
    const state = reactive({
    count: 0
    });
    • 修改响应式数据:当通过组件中的方法来修改数据时,Proxy 能够自动拦截这些变化,并触发视图的重新渲染。
  4. Proxy 的其他应用: 除了 Vue 3 之外,还有其他库使用了 Proxy,例如 dobimmer。这些库利用 Proxy 对对象进行读写拦截,在读写中做一些额外的判断和操作。
    Proxy 对象为 JavaScript 提供了强大的代理功能,使得开发者可以对对象的操作进行更细粒度的控制和拦截。在 Vue 3 中,Proxy 的使用极大地增强了框架的响应式能力和性能。

实例

Proxy 是 JavaScript 中的一个内置对象,用于创建一个对象的代理,从而在访问对象的属性和方法时进行拦截和自定义操作。以下是一些使用 Proxy 的实例:

1. 数据验证

使用 Proxy 可以在设置对象属性时进行数据验证,确保数据的正确性和一致性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const person = {
name: '',
age: 0
};
const personProxy = new Proxy(person, {
set(target, property, value) {
if (property === 'age' && typeof value !== 'number') {
throw new Error('Age must be a number');
}
if (property === 'name' && typeof value !== 'string') {
throw new Error('Name must be a string');
}
target[property] = value;
return true;
}
});
personProxy.name = 'Kimi'; // 正常设置
personProxy.age = 25; // 正常设置
// personProxy.age = '25'; // 抛出错误:Age must be a number

2. 日志记录

通过 Proxy 可以在访问对象属性或方法时自动记录日志,方便调试和监控。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const obj = {
a: 1,
b: 2
};
const loggingProxy = new Proxy(obj, {
get(target, property) {
console.log(`Accessing property: ${property}`);
return target[property];
},
set(target, property, value) {
console.log(`Setting property: ${property} to ${value}`);
target[property] = value;
return true;
}
});
console.log(loggingProxy.a); // 输出:Accessing property: a
loggingProxy.b = 3; // 输出:Setting property: b to 3

3. 实现私有属性

使用 Proxy 可以模拟私有属性的行为,防止外部直接访问对象的某些属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const privateObj = {
_privateData: 'secret',
publicData: 'public'
};
const privateProxy = new Proxy(privateObj, {
get(target, property) {
if (property.startsWith('_')) {
throw new Error('Cannot access private property');
}
return target[property];
}
});
console.log(privateProxy.publicData); // 输出:public
// console.log(privateProxy._privateData); // 抛出错误:Cannot access private property

4. 模拟数组

通过 Proxy 可以创建一个类似数组的对象,并在访问数组元素时进行自定义操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const arrayLike = new Proxy({}, {
get(target, property) {
if (property === 'length') {
return Object.keys(target).length;
}
return target[property];
},
set(target, property, value) {
target[property] = value;
return true;
}
});
arrayLike[0] = 'a';
arrayLike[1] = 'b';
console.log(arrayLike.length); // 输出:2

5. 惰性加载

使用 Proxy 可以实现对象的惰性加载,仅在实际访问属性时才加载数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
const lazyData = {
data: null
};
const lazyProxy = new Proxy(lazyData, {
get(target, property) {
if (property === 'data' && target.data === null) {
console.log('Loading data...');
target.data = { name: 'Kimi', age: 25 };
}
return target[property];
}
});
console.log(lazyProxy.data); // 输出:Loading data... { name: 'Kimi', age: 25 }

这些实例展示了 Proxy 在不同场景下的应用,通过拦截和自定义对象的访问行为,可以实现更灵活和强大的功能.

Promise

Promise

promise

JavaScript 中的 Promise 是一种用于异步编程的对象,它代表了一个异步操作的最终完成(或失败)及其结果值。Promise 有三种状态:

  1. Pending(等待中):初始状态,既不是成功,也不是失败状态。
  2. Fulfilled(已成功):意味着操作成功完成。
  3. Rejected(已失败):意味着操作失败。
    一个 Promise 对象有以下几个方法:
  • Promise.prototype.then():在 Promise 成功时执行,可以链式调用。
  • Promise.prototype.catch():在 Promise 失败时执行,用于错误处理。
  • Promise.prototype.finally():无论 Promise 成功还是失败,都会执行。

创建 Promise

创建一个 Promise 对象通常使用 new Promise 构造函数,并提供一个执行器函数(executor function),它将在 Promise 创建后立即执行:

1
2
3
4
5
6
7
8
let myPromise = new Promise((resolve, reject) => {
// 异步操作
if (/* 异步操作成功 */) {
resolve(value); // 将 Promise 状态设置为成功,并返回 value
} else {
reject(error); // 将 Promise 状态设置为失败,并返回 error
}
});

使用 Promise

1
2
3
4
5
6
7
myPromise.then((value) => {
// 当 Promise 成功时,这里的代码将被执行
}).catch((error) => {
// 当 Promise 失败时,这里的代码将被执行
}).finally(() => {
// 不管 Promise 成功还是失败,这里的代码都将被执行
});

Promise 链

Promise 可以被链式调用,因为 then()catch() 方法都会返回一个新的 Promise 对象:

1
2
3
4
5
6
7
8
9
10
11
myPromise
.then((value) => {
// 处理第一个异步操作的结果
return anotherAsyncOperation(value);
})
.then((result) => {
// 处理第二个异步操作的结果
})
.catch((error) => {
// 处理所有 Promise 链中的错误
});

Promise.all()

Promise.all() 方法用于处理多个 Promise 对象,并且只有当所有 Promise 都成功时,才会返回结果:

1
2
3
4
5
6
7
Promise.all([promise1, promise2, promise3])
.then(([result1, result2, result3]) => {
// 所有 Promise 都成功时,这里的代码将被执行
})
.catch((error) => {
// 任何一个 Promise 失败时,这里的代码将被执行
});

Promise.race()

Promise.race() 方法同样用于处理多个 Promise 对象,但是只要有一个 Promise 完成(无论是成功还是失败),就会立即返回结果:

1
2
3
4
5
6
7
Promise.race([promise1, promise2, promise3])
.then((value) => {
// 第一个完成的 Promise 的结果将被返回
})
.catch((error) => {
// 第一个完成的 Promise 的错误将被返回
});

Promise 是 JavaScript 异步编程的基础,提供了一种更加清晰和可控的方式来处理异步操作。

使用场景

JavaScript 中的 Promise 被广泛用于处理异步操作,以下是一些常见的使用场景:

  1. 异步请求(如 AJAX)
    Promise 可以用于处理 HTTP 请求,例如使用 fetch API 时,fetch 本身返回一个 Promise 对象,可以链式调用 thencatch 来处理请求成功和失败的情况。
    1
    2
    3
    4
    fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
  2. 定时操作(如 setTimeout)
    虽然 setTimeout 本身不是基于 Promise 的,但你可以创建一个返回 Promise 的函数来模拟异步延迟。
    1
    2
    3
    4
    function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
    }
    delay(1000).then(() => console.log('1 second passed'));
  3. 文件读取和写入
    在 Node.js 中,fs 模块提供了基于 Promise 的 API(例如 fs.promises),允许你以异步方式读取和写入文件。
    1
    2
    3
    4
    const fs = require('fs').promises;
    fs.readFile('file.txt', 'utf8')
    .then(data => console.log(data))
    .catch(err => console.error(err));
  4. 数据库操作
    许多数据库库提供了基于 Promise 的 API,使得你可以以异步方式查询和操作数据库。
    1
    2
    3
    database.query('SELECT * FROM users')
    .then(users => console.log(users))
    .catch(error => console.error(error));
  5. 并行执行多个异步操作
    使用 Promise.all 可以同时执行多个异步操作,并在所有操作都成功完成时返回结果。
    1
    2
    3
    4
    5
    6
    7
    Promise.all([fetch(url1), fetch(url2)])
    .then(responses => Promise.all(responses.map(res => res.json())))
    .then(data => {
    console.log(data[0]); // 第一个请求的结果
    console.log(data[1]); // 第二个请求的结果
    })
    .catch(error => console.error(error));
  6. 串行执行多个异步操作
    通过链式调用 then 方法,可以确保异步操作按顺序执行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    fetch(url1)
    .then(response1 => response1.json())
    .then(data1 => {
    return fetch(url2);
    })
    .then(response2 => response2.json())
    .then(data2 => {
    console.log(data1, data2);
    })
    .catch(error => console.error(error));
  7. 错误处理
    Promisecatch 方法提供了一个集中处理异步操作中出现错误的地方。
    1
    2
    3
    4
    5
    6
    fetch(url)
    .then(response => response.json())
    .catch(error => {
    // 处理请求或解析过程中的错误
    console.error('Failed to fetch:', error);
    });
  8. 动态加载模块
    在支持动态 import() 的环境中,import() 返回一个 Promise,可以用来按需加载 JavaScript 模块。
    1
    2
    3
    4
    5
    import(/* webpackChunkName: "feature-module" */ './feature-module')
    .then(module => {
    module.loadFeature();
    })
    .catch(error => console.error('Module loading failed:', error));
  9. 事件监听
    虽然不是直接使用 Promise,但可以通过封装事件监听器来返回 Promise,使得可以以异步方式等待某个事件的发生。
    1
    2
    3
    4
    5
    6
    function waitForEvent(eventType) {
    return new Promise(resolve => {
    document.addEventListener(eventType, resolve, { once: true });
    });
    }
    waitForEvent('click').then(event => console.log('Clicked!', event));
    Promise 提供了一种强大的方式来处理异步操作,使得代码更加清晰和易于维护。

Promise 和 async/await 有什么区别?

async和await
Promiseasync/await 都是JavaScript中处理异步操作的工具,但它们在语法和使用上有所不同。以下是它们之间的一些主要区别:

  1. 语法和可读性
    • Promise:使用 .then().catch() 方法来处理异步操作的结果和错误。代码可能看起来像“回调地狱”(callback hell),尤其是在多个异步操作嵌套时。
    • async/await:提供了一种更接近同步代码的写法,使得异步代码更易于阅读和维护。async 关键字用于声明一个函数是异步的,而 await 关键字用于等待一个 Promise 解决。
  2. 错误处理
    • Promise:错误通过 .catch() 方法捕获,这要求每个异步操作都必须被包裹在 try/catch 块中,或者链式调用 .catch()
    • async/await:错误可以通过传统的 try/catch 块捕获,这使得错误处理更直观和一致。
  3. 控制流
    • Promise:需要链式调用 .then() 方法来处理后续的异步操作,这可能导致代码难以跟踪。
    • async/await:允许你以线性方式编写异步代码,类似于同步代码,使得控制流更清晰。
  4. 性能
    • Promise:在某些情况下,Promise 可能比 async/await 稍微快一些,因为 async/await 实际上是基于 Promise 实现的。
    • async/await:虽然它提供了更好的语法糖,但在底层,async/await 仍然依赖于 Promise,因此性能差异通常可以忽略不计。
  5. 使用场景
    • Promise:适用于需要链式调用多个异步操作的场景,或者当你需要在异步操作完成后执行多个回调函数时。
    • async/await:适用于需要等待单个异步操作完成的场景,或者当你想要以同步的方式编写异步代码时。
  6. 兼容性
    • Promise:在ES6中引入,已被广泛支持。
    • async/await:在ES2017中引入,兼容性较好,但可能在一些旧的JavaScript环境中不被支持。
  7. 代码简洁性
    • Promise:在处理多个异步操作时,代码可能会变得复杂和冗长。
    • async/await:通常可以减少代码量,使其更加简洁和易于理解。
      总的来说,async/await 是建立在 Promise 之上的语法糖,它提供了一种更简洁、更直观的方式来处理异步操作。然而,理解 Promise 的工作原理对于深入理解 async/await 以及处理更复杂的异步逻辑是非常重要的。

fetch

fetch 是 JavaScript 中用于发起网络请求的函数,它返回一个 Promise 对象,该对象在请求完成时解析为一个 Response 对象。fetch 提供了一种简单、现代的方式来处理 HTTP 请求和响应。下面是一些关于 fetch 的基本用法和示例:

基本用法

发起 GET 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json(); // 解析响应为 JSON
})
.then(data => {
console.log(data); // 处理数据
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});

在这个示例中,fetch 发起一个 GET 请求到指定的 URL。然后使用 .then() 方法处理响应。首先检查响应是否成功(response.ok),如果成功,则将响应解析为 JSON 格式。最后,处理解析后的数据或捕获并处理错误。

发起 POST 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
key1: 'value1',
key2: 'value2'
})
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});

在这个 POST 请求的示例中,我们设置了请求方法为 POST,并指定了请求头和请求体。请求体被设置为 JSON 字符串,因此需要在请求头中指定 Content-Typeapplication/json

使用 async/await

使用 asyncawait 可以使 fetch 请求的代码更加简洁和易于理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('There was a problem with the fetchData operation:', error);
}
}
fetchData();

响应类型

  • .json():将响应体解析为 JSON 格式。
  • .text():将响应体解析为文本。
  • .blob():将响应体解析为 Blob 对象,适用于二进制数据。
  • .formData():将响应体解析为 FormData 对象,适用于表单数据。

错误处理

  • 网络错误:如果网络请求失败(例如,无法连接到服务器),fetch 会抛出一个异常,可以在 .catch() 中捕获。
  • HTTP 错误:如果服务器返回一个非 200 系列的状态码,fetch 仍然会解析为 Promise,但 response.ok 会为 false。需要手动检查 response.okresponse.status 来处理这种情况.

注意事项

  • CORS(跨源资源共享)fetch 请求可能会受到 CORS 策略的限制。如果请求的资源来自不同的源,服务器需要设置适当的 CORS 头以允许请求。
  • 请求超时fetch 本身没有内置的超时机制。如果需要实现超时功能,可以通过 Promise.race 或其他方法来实现.
  • 重试机制:在某些情况下,可能需要对失败的请求进行重试。可以编写一个重试逻辑来处理这种情况.
    fetch 是现代 Web 开发中常用的 API,它提供了一种简单而强大的方式来处理网络请求和响应。

async 和 await

async/await 是 JavaScript 中用于简化异步编程的两个关键字,它们基于 Promise 对象,使得异步代码的编写和阅读更接近同步代码的风格,从而提高代码的可读性和可维护性。

Async 关键字

  • async 关键字用于声明一个函数是异步的。当一个函数被声明为 async 时,它会隐式返回一个 Promise 对象。
  • async 函数内部可以包含 await 表达式,但只能包含一个 await 表达式。

Await 关键字

  • await 关键字用于等待一个 Promise 解决(resolve)或拒绝(reject)。
  • await 只能在 async 函数内部使用。
  • 当执行到 await 表达式时,JavaScript 运行时会暂停该 async 函数的执行,直到等待的 Promise 完成(解决或拒绝)。
  • 如果 Promise 成功解决,await 表达式的结果是解决的值;如果 Promise 被拒绝,await 表达式会抛出拒绝的原因。

使用示例

基本使用

1
2
3
4
5
6
7
8
9
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Failed to fetch data:', error);
}
}

在这个例子中,fetchData 是一个 async 函数,它使用 await 等待 fetch 请求的结果。如果请求成功,它将解析 JSON 并打印数据。如果请求失败,它将捕获错误并打印错误信息。

错误处理

async/await 允许使用传统的 try/catch 块来处理错误,这使得错误处理更加直观。

1
2
3
4
5
6
7
8
9
10
11
12
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Failed to fetch data:', error);
}
}

并行执行异步操作

虽然 async/await 使得代码看起来是同步的,但它仍然可以并行执行异步操作。

1
2
3
4
5
async function fetchMultipleUrls(urls) {
const promises = urls.map(url => fetch(url).then(res => res.json()));
const results = await Promise.all(promises);
console.log(results);
}

在这个例子中,fetchMultipleUrls 函数并行地对多个 URL 发起 fetch 请求,并等待所有请求完成。

注意事项

  • await 会暂停 async 函数的执行,直到等待的 Promise 解决。这可能会导致性能问题,特别是在 I/O 密集型操作中,因此应该谨慎使用。
  • 在循环中使用 await 会逐个等待每个迭代的 Promise,这可能不是你想要的行为,特别是在需要并行执行异步操作时。
    async/await 提供了一种更简洁和直观的方式来处理异步代码,使得异步编程更加接近同步编程的体验。

实例

  • then 有两个参数都是回调函数,第一个回调函数,在Promise  状态为 resolve 执行,第二个在状态为reject执行。catch方法,相当于then(null,reject)的一个变体。

前代的区别

Promise 是 JavaScript 中处理异步操作的一种更现代、更强大的方式,与之前的回调函数(Callback)和事件(Event)等异步处理方式相比,Promise 有以下几个显著的区别和优势:

一、回调函数(Callback)

  1. 定义
    • 回调函数是一种将函数作为参数传递给另一个函数,并在某个操作完成后调用该函数的方式。这是早期 JavaScript 中处理异步操作的主要方式。
    • 示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      function fetchData(callback) {
      setTimeout(() => {
      const data = '成功获取数据';
      callback(data);
      }, 1000);
      }
      fetchData((data) => {
      console.log(data); // 输出 '成功获取数据'
      });
  2. 问题
    • 回调地狱(Callback Hell):当多个异步操作需要顺序执行时,回调函数会嵌套多层,导致代码难以阅读和维护。
      1
      2
      3
      4
      5
      6
      7
      fetchData((data1) => {
      processData(data1, (data2) => {
      saveData(data2, (result) => {
      console.log(result);
      });
      });
      });
    • 错误处理困难:每个回调函数都需要单独处理错误,代码冗余且难以管理。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      fetchData((err, data1) => {
      if (err) {
      console.error(err);
      return;
      }
      processData(data1, (err, data2) => {
      if (err) {
      console.error(err);
      return;
      }
      saveData(data2, (err, result) => {
      if (err) {
      console.error(err);
      return;
      }
      console.log(result);
      });
      });
      });

二、事件(Event)

  1. 定义
    • 事件是一种基于事件驱动模型的异步处理方式。通过监听事件,当事件发生时执行特定的处理函数。
    • 示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      const eventEmitter = new EventEmitter();
      eventEmitter.on('data', (data) => {
      console.log(data); // 输出 '成功获取数据'
      });
      function fetchData() {
      setTimeout(() => {
      const data = '成功获取数据';
      eventEmitter.emit('data', data);
      }, 1000);
      }
      fetchData();
  2. 问题
    • 事件管理复杂:需要手动管理事件的注册和注销,容易出现内存泄漏。
    • 事件顺序难以控制:多个事件的处理顺序难以保证,容易导致逻辑混乱。

三、Promise

  1. 定义
    • Promise 是一个代表了异步操作最终完成或失败的对象。它提供了一种更简洁、更灵活的方式来处理异步操作。
    • 示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      function fetchData() {
      return new Promise((resolve, reject) => {
      setTimeout(() => {
      const data = '成功获取数据';
      resolve(data);
      }, 1000);
      });
      }
      fetchData().then((data) => {
      console.log(data); // 输出 '成功获取数据'
      }).catch((error) => {
      console.error(error);
      });
  2. 优势
    • 链式调用Promisethen 方法返回一个新的 Promise 对象,可以进行链式调用,使代码更简洁、更易读。
      1
      2
      3
      4
      5
      fetchData()
      .then(data1 => process(data1))
      .then(data2 => save(data2))
      .then(result => console.log(result))
      .catch(error => console.error(error));
    • 错误处理Promisecatch 方法可以捕获链中任何位置的错误,简化了错误处理逻辑。
      1
      2
      3
      4
      5
      fetchData()
      .then(data1 => process(data1))
      .then(data2 => save(data2))
      .then(result => console.log(result))
      .catch(error => console.error(error));
    • 状态管理Promise 有三种状态(Pending、Fulfilled、Rejected),状态一旦改变就不可逆,这使得异步操作的状态管理更加明确。
    • 静态方法Promise 提供了多种静态方法(如 Promise.allPromise.racePromise.resolvePromise.reject),可以方便地处理多个异步操作。
      1
      2
      3
      4
      5
      6
      7
      8
      const promise1 = Promise.resolve(1);
      const promise2 = Promise.resolve(2);
      const promise3 = Promise.resolve(3);
      Promise.all([promise1, promise2, promise3]).then((results) => {
      console.log(results); // 输出 [1, 2, 3]
      }).catch((error) => {
      console.error(error);
      });

四、总结

  • 回调函数
    • 优点:简单直接,适用于简单的异步操作。
    • 缺点:回调地狱,错误处理困难,代码难以维护。
  • 事件
    • 优点:适用于多对多的事件驱动模型,适用于DOM事件处理。
    • 缺点:事件管理复杂,事件顺序难以控制,容易导致逻辑混乱。
  • Promise
    • 优点:链式调用,错误处理简单,状态管理明确,提供多种静态方法,代码更简洁、更易读、更易维护。
    • 缺点:学习曲线稍陡,需要理解Promise的三种状态和链式调用的机制。
      通过使用 Promise,可以更有效地处理复杂的异步操作,使代码更加简洁、易读和易维护。

Js中的正则表达式

RegExp 对象

RegExp 对象

RegExp 对象是 JavaScript 中用于处理正则表达式的内置对象。它提供了一种强大的方式来匹配、搜索和替换字符串中的文本模式。以下是关于 RegExp 对象的详细介绍:

1. 创建 RegExp 对象

1.1 使用字面量语法

1
let regex = /pattern/flags;
  • pattern:要匹配的文本模式。
  • flags:可选的标志,用于修改匹配行为。常见的标志有:
    • g:全局匹配,匹配所有符合条件的子字符串。
    • i:忽略大小写,进行不区分大小写的匹配。
    • m:多行匹配,使 ^$ 在多行模式下工作,即匹配每一行的开始和结束。
    • s:允许点号(.)匹配换行符。
    • u:Unicode 模式,正确处理 Unicode 字符。
    • y:粘性匹配,从上次匹配结束的位置开始匹配。

1.2 使用构造函数

1
let regex = new RegExp(pattern, flags);
  • pattern:要匹配的文本模式,可以是字符串或另一个 RegExp 对象。
  • flags:可选的标志,用于修改匹配行为。

2. RegExp 对象的属性

2.1 source

  • 描述:返回正则表达式的文本内容。
  • 示例
    1
    2
    let regex = /abc/g;
    console.log(regex.source); // 'abc'

2.2 flags

  • 描述:返回正则表达式使用的标志。
  • 示例
    1
    2
    let regex = /abc/gi;
    console.log(regex.flags); // 'gi'

2.3 global

  • 描述:布尔值,表示是否设置了 g 标志。
  • 示例
    1
    2
    let regex = /abc/g;
    console.log(regex.global); // true

2.4 ignoreCase

  • 描述:布尔值,表示是否设置了 i 标志。
  • 示例
    1
    2
    let regex = /abc/i;
    console.log(regex.ignoreCase); // true

2.5 multiline

  • 描述:布尔值,表示是否设置了 m 标志。
  • 示例
    1
    2
    let regex = /abc/m;
    console.log(regex.multiline); // true

2.6 lastIndex

  • 描述:一个整数,表示下一次匹配的开始位置。仅在全局匹配模式下有效。
  • 示例
    1
    2
    3
    4
    5
    6
    let regex = /a/g;
    let str = 'aaa';
    regex.exec(str); // ['a']
    console.log(regex.lastIndex); // 1
    regex.exec(str); // ['a']
    console.log(regex.lastIndex); // 2

3. RegExp 对象的方法

3.1 exec(string)

  • 描述:在指定字符串中执行一个搜索匹配。如果匹配成功,则返回一个结果数组;否则返回 null。结果数组包含以下属性:
    • 0:匹配的整个字符串。
    • 123 等:捕获组的内容。
    • index:匹配的起始位置。
    • input:原始字符串。
    • groups:命名捕获组的对象。
  • 示例
    1
    2
    3
    4
    5
    6
    let regex = /a(b)c/g;
    let str = 'abcabc';
    let result = regex.exec(str);
    console.log(result); // ['abc', 'b', index: 0, input: 'abcabc', groups: undefined]
    console.log(result[0]); // 'abc'
    console.log(result[1]); // 'b'

3.2 test(string)

  • 描述:在指定字符串中执行一个搜索匹配。如果匹配成功,则返回 true;否则返回 falsetest 方法不返回匹配结果,仅返回布尔值。
  • 示例
    1
    2
    3
    let regex = /a/g;
    let str = 'abc';
    console.log(regex.test(str)); // true

3.3 toString()

  • 描述:返回正则表达式的字符串表示形式。
  • 示例
    1
    2
    let regex = /abc/gi;
    console.log(regex.toString()); // '/abc/gi'

4. 示例

4.1 匹配和替换

1
2
3
4
let str = 'Hello, World!';
let regex = /World/g;
let newStr = str.replace(regex, 'JavaScript');
console.log(newStr); // 'Hello, JavaScript!'

4.2 全局匹配

1
2
3
4
let str = 'abcabcabc';
let regex = /abc/g;
let matches = str.match(regex);
console.log(matches); // ['abc', 'abc', 'abc']

4.3 命名捕获组

1
2
3
4
let str = '2023-10-10';
let regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let result = str.match(regex);
console.log(result.groups); // { year: '2023', month: '10', day: '10' }

5. 总结

RegExp 对象是 JavaScript 中处理正则表达式的核心工具,提供了丰富的属性和方法来执行匹配、搜索和替换操作。掌握 RegExp 对象的使用,可以帮助你更高效地处理字符串和文本模式匹配。

1
2
3
var patt=new RegExp(pattern,modifiers);  
或者更简单的方式:
var patt=/pattern/modifiers;
  • pattern(模式) 描述了表达式的模式
  • modifiers(修饰符) 用于指定全局匹配、区分大小写的匹配和多行匹配
1
2
var re = new RegExp("\\w+");
var re = /\w+/;

一般而言正则表达式由下面几点组成,详情查看正则表达式

  • 修饰符
  • 方括号
  • 元字符
  • 量词

RegExp 对象方法

RegExp 对象属性

支持正则表达式的 String 对象的方法

在 JavaScript 中,String 对象提供了几个支持正则表达式的方法,这些方法可以用于执行各种字符串匹配、搜索、替换等操作。以下是一些常用的 String 方法及其使用示例:

1. match()

match() 方法对字符串执行匹配搜索,并将匹配的结果作为数组返回。如果没有匹配,则返回 null

语法

1
str.match(regexp)

示例

1
2
3
4
const text = 'Hello world! Welcome to the world of JavaScript.';
const pattern = /world/g;
const matches = text.match(pattern);
console.log(matches); // ['world', 'world']

2. matchAll()

matchAll() 方法返回一个包含所有匹配项的迭代器。每个匹配项都是一个数组,包含匹配结果和捕获组。

语法

1
str.matchAll(regexp)

示例

1
2
3
4
5
6
const text = 'Hello world! Welcome to the world of JavaScript.';
const pattern = /world/g;
const matches = text.matchAll(pattern);
for (const match of matches) {
console.log(match); // ['world', index: 6, input: 'Hello world! Welcome to the world of JavaScript.', groups: undefined]
}

search() 方法执行匹配搜索,返回匹配项的索引,如果没有匹配,则返回 -1

语法

1
str.search(regexp)

示例

1
2
3
4
const text = 'Hello world! Welcome to the world of JavaScript.';
const pattern = /world/;
const index = text.search(pattern);
console.log(index); // 6

4. replace()

replace() 方法在字符串中查找匹配项,然后使用新的子字符串替换匹配项。可以使用字符串或正则表达式来指定匹配项,可以使用字符串或函数来指定替换项。

语法

1
str.replace(regexp|substr, newSubStr|function)

示例

1
2
3
4
const text = 'Hello world! Welcome to the world of JavaScript.';
const pattern = /world/g;
const newText = text.replace(pattern, 'universe');
console.log(newText); // 'Hello universe! Welcome to the universe of JavaScript.'

5. split()

split() 方法使用指定的分隔符字符串将一个字符串分割成多个子字符串,并将结果作为数组返回。分隔符可以是一个字符串或正则表达式。

语法

1
str.split(separator, limit)

示例

1
2
3
4
const text = 'Hello world! Welcome to the world of JavaScript.';
const pattern = /\s+/; // 匹配一个或多个空白字符
const words = text.split(pattern);
console.log(words); // ['Hello', 'world!', 'Welcome', 'to', 'the', 'world', 'of', 'JavaScript.']

6. includes()

includes() 方法用于检测一个字符串是否包含另一个指定的子字符串。虽然这个方法不直接使用正则表达式,但可以通过正则表达式预处理字符串来实现类似的功能。

语法

1
str.includes(searchString, position)

示例

1
2
3
4
5
6
7
8
const text = 'Hello world! Welcome to the world of JavaScript.';
const pattern = /world/;
const match = pattern.exec(text);
if (match) {
const index = match.index;
const substring = text.slice(index, index + match[0].length);
console.log(text.includes(substring)); // true
}

7. startsWith()endsWith()

startsWith()endsWith() 方法用于检测一个字符串是否以指定的子字符串开头或结尾。虽然这些方法不直接使用正则表达式,但可以通过正则表达式预处理字符串来实现类似的功能。

语法

1
2
str.startsWith(searchString, position)
str.endsWith(searchString, length)

示例

1
2
3
4
5
6
7
const text = 'Hello world! Welcome to the world of JavaScript.';
const patternStart = /^Hello/;
const patternEnd = /JavaScript\.$/;
const matchStart = patternStart.test(text);
const matchEnd = patternEnd.test(text);
console.log(matchStart); // true
console.log(matchEnd); // true

总结

这些 String 方法结合正则表达式,提供了强大的字符串处理功能,可以满足各种复杂的字符串操作需求。通过这些方法,可以轻松实现字符串的匹配、搜索、替换和分割等操作。
JavaScript RegExp 对象