JavaScript内置对象简介

JavaScript内置对象简介

概述

JavaScript 内置对象(built-in objects)是 JavaScript 语言提供的预定义对象,它们提供了基本的功能和方法,可以直接在代码中使用。

关于JavaScript内置对象更多情况可见 MDN文档Standard built-in objects - JavaScript | MDN

其开端部分,不太好理解,特地节选补注:

This chapter documents all of JavaScript's standard, built-in objects, including their methods and properties.

本章介绍和说明了 JavaScript 中所有的标准内置对象、以及它们的方法和属性。

The term "global objects" (or standard built-in objects) here is not to be confused with the global object. Here, "global objects" refer to objects in the global scope.

这里的术语“全局对象”(或标准内置对象)不应与 global 对象混淆。这里的“全局对象”指的是处在全局作用域里的多个对象

【译注:全局对象通常指的是 JavaScript 环境中的顶级对象,如在浏览器中的 window 对象。而这里的“全局对象”(或“标准内置对象”)指的是像 Array、Date、Math 等无需创建实例就可以使用的对象。】

The global object itself can be accessed using the this operator in the global scope. In fact, the global scope consists of the properties of the global object, including inherited properties, if any.

global 对象可以在全局作用域里通过使用 this 访问到【译注:但只有在 ECMAScript 5 的非严格模式下才可以,在严格模式下得到的是 undefined】。其实,全局作用域包含全局对象中的属性,包括它可能继承来的属性(如果有的话)。

Other objects in the global scope are either created by the user script or provided by the host application. The host objects available in browser contexts are documented in the API reference.

全局作用域中的其他对象则可由用户的脚本创建,或由宿主程序提供。浏览器环境中所提供的宿主对象的说明可以在这里找到:API 参考

【译注:用户脚本创建,例如,用户定义的变量或函数,以及浏览器提供的 Document 对象都属于这个范畴。宿主对象是由浏览器提供的,与 JavaScript 语言核心分开的对象,如 Document、Window 等。】

For more information about the distinction between the DOM and core JavaScript, see JavaScript technologies overview.

要了解关于 DOM 和核心 JavaScript 之间区别的更多信息,可参阅 JavaScript 技术概述

内置对象是 JavaScript 语言的核心部分,它们提供了丰富的方法和属性,使得开发者可以更加高效地编写代码。这些内置对象扩展了 JavaScript 的能力,使其能够处理各种常见的编程任务。随着 JavaScript 语言的发展,可能还会有更多的内置对象加入到标准中。

以下是JavaScript的一些主要内置对象:

  • Math:提供了一系列的数学常数和函数,用于进行常见的数学运算,如Math.random()(生成一个随机数)、Math.floor()(取整)和Math.sqrt()(开平方)等。
  • Date:用于处理日期和时间。可以用于创建允许创建、解析和格式化日期和时间,比较日期,计算日期等。例如,new Date() 可以创建一个表示当前日期和时间的对象。
  • String:用于处理字符串(文本数据)。提供了许多方法来操作字符串,如charAt()(获取特定位置的字符)、concat()(连接两个或多个字符串)、indexOf()(查找特定字符串的位置)等。
  • Array:用于处理数组的对象,数组可以存储多个值,并提供了许多方法来操作这些值,如push()(添加一个或多个元素到数组的末尾)、pop()(删除并返回数组的最后一个元素)、shift()(删除并返回数组的第一个元素)等。
  • Object:所有其他JavaScript对象都是从Object对象派生出来的,Object 是 JavaScript 中所有对象的父对象。Object对象本身主要提供了一种将属性名映射到值的方法。
  • Number:用于处理数字。提供了许多方法来操作数字,如parseInt()(将字符串解析为整数)、parseFloat()(将字符串解析为浮点数)等。
  • Boolean:有两个可能的值:true和false,用于进行逻辑比较和条件判断。
  • RegExp:用于处理正则表达式。提供了许多方法来操作正则表达式,如test()(检查一个字符串是否匹配某个模式)等。
  • Function:函数是一段可调用的代码,可以接收参数并可能返回一个值。函数可以嵌套在其他函数或表达式中,也可以作为参数传递给其他函数或方法。
  • Error 和 Error.prototype:JavaScript提供了一个Error对象,用于处理错误。Error对象有一个message属性,描述了发生的错误。此外,JavaScript还提供了几种内置的错误类型,如SyntaxError、TypeError等。
  • Promise 和 Promise.prototype:Promise是一个异步编程的解决方案,它提供了一种方式来组织和管理异步操作的结果。Promise对象代表了一个异步操作的最终完成(或失败)及其结果值。Promise 对象是在 ECMAScript 6(ES6)标准中引入的。
  • Map, Set, WeakMap, WeakSet:这些是ES6引入的新数据结构。Map对象保存键值对,并记住键的原始插入顺序。Set对象只存储唯一值,值在Set中自动按插入顺序排序。WeakMap与Map类似,但它允许键是任何类型(包括非对象类型和循环引用)。WeakSet类似于Set,但它允许包含任何类型的键(包括不可达的对象)。
  • Symbol:ES6引入了Symbol类型,它表示一个唯一且不可变的数据类型,经常被用作对象的键值或者Map的键。
  • Proxy 和 Proxy.prototype:ES6引入了Proxy对象,允许你定义基本操作的自定义行为。例如,你可以用Proxy来定义一个对象的读取行为,或者改变一个对象的读取行为。
  • Reflect 和 Reflect.prototype:ES6引入了Reflect对象,提供了一些静态方法,它们的行为与一些原始对象的方法类似,但不是直接在原始对象上调用这些方法。

下面选取几个JavaScript内置对象具体介绍

☆Array 对象

JavaScript 的 Array 是一种内置对象(有时也称为全局对象),用于构造数组,是灵活的数据结构,可以存储不同类型的数据,并提供了丰富的方法来操作这些数据。

JavaScript 的 Array 是一种全局对象,用于构造数组,它是高级的、类似列表的对象。

特点

  • 动态大小:数组的大小不是固定的,可以动态地添加或删除元素。
  • 异质性:数组可以包含任意类型的值,比如数字、字符串、对象甚至其他数组。
  • 零基索引:数组的索引从0开始,第一个元素的索引是0,第二个元素的索引是1,依此类推。
  • 长度属性:length 属性表示数组中元素的数量。
  • 原型方法:Array.prototype 上定义了许多方法,用于遍历、映射、过滤、排序和搜索数组。
  • 高阶函数:支持函数式编程方法,如 map(), filter(), reduce() 等。

创建数组

创建数组的方法有几种:

  1. 字面量语法

let fruits = ['Apple', 'Banana', 'Cherry'];

  1. 使用构造函数

let fruits = new Array('Apple', 'Banana', 'Cherry');

  1. 使用静态方法

let fruits = Array.of('Apple', 'Banana', 'Cherry');

使用数组

一旦创建了数组,就可以使用多种方法来操作数组:

  • 访问元素:使用下标访问数组元素。

console.log(fruits[0]); // 输出: Apple

  • 修改元素:通过下标修改数组元素的值。

fruits[1] = 'Blackberry'; // 将第二个元素更改为 'Blackberry'

  • 数组方法:使用数组的内置方法。

fruits.push('Dragonfruit'); // 在数组的末尾添加新元素

let firstFruit = fruits.shift(); // 移除数组的第一个元素并返回它

fruits.sort(); // 对数组的元素进行排序

  • 遍历数组:使用循环或数组的迭代方法。

for (let i = 0; i < fruits.length; i++) {

  console.log(fruits[i]);

}

// 或者使用 forEach 方法

fruits.forEach(fruit => console.log(fruit));

  • 数组解构:ES6 引入了解构赋值,可以方便地从数组中提取值。

let [first, second] = fruits;

console.log(first); // 输出: Apple

console.log(second); // 输出: Blackberry

☆ Function 对象

JavaScript 中的函数是核心概念,它们提供了强大的编程能力。函数的灵活性和一等公民的特性使得 JavaScript 成为一个功能丰富的、表达性强的语言。

特点

  • 一等公民:在 JavaScript 中,函数是“一等公民”,意味着它们可以像任何其他对象一样被传递、赋值和拥有属性。
  • 对象:函数本身是对象,因此它们可以拥有属性和方法。
  • 作用域:函数可以访问它们被定义时的作用域中的变量,这是闭包(closure)的基础。
  • 构造器:Function 构造器可以创建新的函数对象,但不推荐这种方式,因为它类似于 eval,存在安全风险并且效率较低。
  • 原型:所有 JavaScript 函数都是 Function 的实例,它们都继承自 Function.prototype。

创建函数

创建函数的方法有几种:

  1. 函数声明

function greet(name) {

  return `Hello, ${name}!`;

}

  1. 函数表达式

const greet = function(name) {

  return `Hello, ${name}!`;

};

  1. 箭头函数(ES6 引入):

const greet = name => `Hello, ${name}!`;

  1. Function 构造器(不推荐):

const greet = new Function('name', 'return `Hello, ${name}!`;');

使用函数

  • 调用函数:使用圆括号调用函数,并传递参数。

console.log(greet('Alice')); // 输出: Hello, Alice!

  • 函数方法:使用 .call(), .apply(), 或 .bind() 方法在特定的上下文中调用函数。

const person = { name: 'Bob' };

const greetBob = greet.bind(person);

console.log(greetBob()); // 输出: Hello, Bob!

  • 高阶函数:函数可以作为参数传递给其他函数,或者作为其他函数的返回值。

function processUserInput(callback) {

  const name = prompt('Please enter your name.');

  console.log(callback(name));

}

processUserInput(greet);

  • 闭包:函数可以记住并访问它们创建时的作用域,即使是在当前作用域之外。

function createGreeting(greeting) {

  return function(name) {

    return `${greeting}, ${name}!`;

  };

}

const sayHello = createGreeting('Hello');

console.log(sayHello('Alice')); // 输出: Hello, Alice!

☆Math 对象

JavaScript 的 Math 对象提供了一系列的属性和方法,用于执行常见的数学运算。Math 是一个内置对象,它具有数学常数和函数的属性和方法。不像其他全局对象,Math 不是一个构造函数。所有在 Math 对象中的属性和方法都是静态的。

Math 对象的属性

Math 对象包含了多个数学常数的属性,例如:

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

数学常数使用示例:

// 圆周率 PI

console.log(Math.PI); // 输出: 3.141592653589793

// 自然对数的底数 E

console.log(Math.E); // 输出: 2.718281828459045

// 2 的平方根

console.log(Math.SQRT2); // 输出: 1.4142135623730951

Math 对象的方法

Math 对象提供了大量的方法来执行数学运算:

四舍五入和取整

  • Math.round(x):返回 x 四舍五入后的整数。
  • Math.ceil(x):返回大于或等于 x 的最小整数。
  • Math.floor(x):返回小于或等于 x 的最大整数。
  • Math.trunc(x):返回 x 的整数部分,去除小数。

幂和根

  • Math.pow(x, y):返回 x 的 y 次幂。
  • Math.sqrt(x):返回 x 的平方根。
  • Math.cbrt(x):返回 x 的立方根。
  • Math.exp(x):返回 E^x,即 E 的 x 次幂。

对数

  • Math.log(x):返回 x 的自然对数(底为 E)。
  • Math.log10(x):返回 x 的以 10 为底的对数。
  • Math.log2(x):返回 x 的以 2 为底的对数。

三角函数

  • 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 轴到点 (x, y) 的角度(以弧度计)。

随机数

  • Math.random():返回一个介于 0(包含)和 1(不包含)之间的伪随机数。

最大值和最小值

  • Math.max([x[, y[, …]]]):返回零个或更多个数值的最大值。
  • Math.min([x[, y[, …]]]):返回零个或更多个数值的最小值。

绝对值

  • Math.abs(x):返回 x 的绝对值。

符号

  • Math.sign(x):返回 x 的符号,表明 x 是正数、负数还是零。

三角函数的超越亲戚

  • Math.sinh(x):返回 x 的双曲正弦值。
  • Math.cosh(x):返回 x 的双曲余弦值。
  • Math.tanh(x):返回 x 的双曲正切值。
  • Math.asinh(x):返回 x 的反双曲正弦值。
  • Math.acosh(x):返回 x 的反双曲余弦值。
  • Math.atanh(x):返回 x 的反双曲正切值。

其他

  • Math.hypot([x[, y[, …]]]):返回所有参数的平方和的平方根。
  • Math.expm1(x):返回 exp(x) - 1,即 E^x - 1。
  • Math.log1p(x):返回 1 + x 的自然对数(底为 E),对于小数值 x,此函数比 Math.log(1+x) 更精确。
  • Math.log10(x):返回以 10 为底的 x 的对数。
  • Math.log2(x):返回以 2 为底的 x 的对数。
  • Math.fround(x):返回最接近的单精度浮点数表示的 x。
  • Math.imul(x, y):返回两个参数的 32 位整数乘积的结果。

常用方法的使用示例

以下是一些如何使用 Math 对象的方法的示例:

// 四舍五入

console.log(Math.round(4.7)); // 输出: 5

// 幂运算

console.log(Math.pow(2, 3)); // 输出: 8

// 平方根

console.log(Math.sqrt(16)); // 输出: 4

// 随机数

console.log(Math.random()); // 输出: 0.123456789 (示例值)

// 最大值和最小值

console.log(Math.max(1, 3, 2)); // 输出: 3

console.log(Math.min(1, 3, 2)); // 输出: 1

// 三角函数

console.log(Math.sin(Math.PI / 2)); // 输出: 1

console.log(Math.cos(Math.PI)); // 输出: -1

// 绝对值

console.log(Math.abs(-10)); // 输出: 10

// 符号

console.log(Math.sign(-10)); // 输出: -1

Math 对象的方法是非常有用的工具,可以帮助你在 JavaScript 中执行各种数学运算。由于它们是静态方法,你可以直接在 Math 对对象上调用它们,而不需要创建 Math 的实例。

数学计算的注意事项

在使用 JavaScript 进行数学计算时,需要注意浮点数的精度问题。由于 JavaScript 使用 IEEE 754 双精度浮点数表示法,这可能导致一些不精确的结果。例如:

console.log(0.1 + 0.2); // 输出: 0.30000000000000004

在处理金融或其他需要高精度的计算时,可能需要使用特定的库来避免这种精度问题。

☆Number对象

JavaScript 的 Number 对象是一个包装对象,允许你处理数值数据。它可以用来表示整数或浮点数。Number 对象还提供了一系列的属性和方法,用于执行数值相关的操作。

Number 对象的属性

Number 对象提供了以下一些有用的静态属性:

  • Number.MAX_VALUE:可能的最大正数。任何大于此值的值都会变成 Infinity。
  • Number.MIN_VALUE:可能的最小正数(即最接近 0 的正数,但不是负数)。任何小于此值的正数都会被转换为 0。
  • Number.NaN:表示非数字值的特殊值。
  • Number.NEGATIVE_INFINITY:表示负无穷大的值。
  • Number.POSITIVE_INFINITY:表示正无穷大的值。
  • Number.EPSILON:表示 1 与大于 1 的最小浮点数之间的差。
  • Number.MAX_SAFE_INTEGER:在 JavaScript 中可以安全表示的最大整数(2^53 - 1)。
  • Number.MIN_SAFE_INTEGER:在 JavaScript 中可以安全表示的最小整数(-(2^53 - 1))。

Number 对象的方法

Number 对象还包含了一系列的方法,用于数值的转换和处理:

  • Number.prototype.toString([radix]):将数字转换为指定基数的字符串表示。
  • Number.prototype.toFixed([digits]):将数字格式化为指定小数位数的字符串。
  • Number.prototype.toExponential([fractionDigits]):将数字转换为指数形式的字符串。
  • Number.prototype.toPrecision([precision]):将数字格式化为指定长度的字符串。
  • Number.prototype.valueOf():返回 Number 对象的原始数值。

全局 Number 函数

JavaScript 还提供了一些全局 Number 函数,可以用来处理数值:

  • parseInt(string[, radix]):解析一个字符串并返回一个整数。
  • parseFloat(string):解析一个字符串并返回一个浮点数。
  • isNaN(value):判断给定的值是否为 NaN。
  • isFinite(value):判断给定的值是否为有限数。
  • isInteger(value):判断给定的值是否为整数。
  • isSafeInteger(value):判断给定的值是否为安全整数(即在 Number.MIN_SAFE_INTEGER 和 Number.MAX_SAFE_INTEGER 之间的整数)。

使用 Number 对象的示例

let num = new Number(123.456);

// 转换为字符串

console.log(num.toString()); // 输出: '123.456'

console.log(num.toString(16)); // 输出: '7b.74bc6a7ef9db22d'

// 格式化为固定小数位数

console.log(num.toFixed(2)); // 输出: '123.46'

// 转换为指数形式

console.log(num.toExponential(1)); // 输出: '1.2e+2'

// 格式化为指定长度

console.log(num.toPrecision(3)); // 输出: '123'

// 获取原始数值

console.log(num.valueOf()); // 输出: 123.456

// 使用全局函数:

  • Number.isNaN(value):确定传递的值是否是 NaN 和其类型是 Number。它是 isNaN 的更严格的版本,不会强制将参数转换为数字。
  • Number.isFinite(value):检查传递的值是否为有限数字。与全局的 isFinite 函数不同,它不会强制将非数字的值转换为数字,这意味着它只对数值类型有效。

创建 Number 对象

通常,我们不需要显式创建一个 Number 对象,因为 JavaScript 会自动将数字字面量转换为 Number 类型。但如果需要创建一个 Number 对象,可以使用 new 关键字:

let numObj = new Number(10);

console.log(typeof numObj); // 输出: 'object'

然而,在实际开发中,直接使用数字字面量更为常见和方便:

let num = 10;

console.log(typeof num); // 输出: 'number'

类型转换

JavaScript 在需要的时候会自动将 Number 对象转换为原始数字值,通常不需要手动调用 valueOf 方法。此外,当你尝试进行数学运算或者比较时,Number 对象会被当作普通数字处理。

注意事项

  • 使用 Number 对象的方法时,不需要显式创建 Number 对象实例。所有的数字字面量都被视为 Number 类型,并且可以访问 Number 原型上的方法。
  • 在进行数值计算时,应当注意浮点数的精度问题。例如,0.1 + 0.2 并不等于 0.3,而是一个非常接近 0.3 的浮点数。这是因为在二进制浮点数中,这些值不能精确表示。
  • 当处理非常大或非常小的数字时,应当注意 Number.MAX_VALUE 和 Number.MIN_VALUE 的限制,以及 Infinity 和 -Infinity 的概念。
  • 安全整数的概念是因为 JavaScript 使用 IEEE 754 双精度浮点数表示所有数字,这意味着超过 Number.MAX_SAFE_INTEGER 或 Number.MIN_SAFE_INTEGER 的整数值可能会失去精度。

使用 Number 对象和方法时,了解这些属性和行为将帮助你更好地处理 JavaScript 中的数值。

☆String对象

JavaScript 中的 String 对象用于处理文本(字符串)数据。字符串可以由双引号("...")、单引号('...')或反引号(`...`)包围,反引号还允许字符串插值和多行字符串。

创建 String 对象

虽然通常直接使用字符串字面量,但也可以使用 new 关键字来创建 String 对象:

let stringObj = new String("Hello, World!");

console.log(typeof stringObj); // 输出: 'object'

然而,大多数情况下,我们会直接使用字符串字面量,因为它们更简洁:

let str = "Hello, World!";

console.log(typeof str); // 输出: 'string'

String 属性和方法

String 对象和字面量都可以访问许多有用的属性和方法:

  • .length:返回字符串的长度。
  • .charAt(index):返回指定索引处的字符。
  • .charCodeAt(index):返回指定索引处字符的 Unicode 编码。
  • .concat(...strings):将一个或多个字符串连接到原字符串。
  • .includes(substring):判断原字符串是否包含指定的子字符串。
  • .indexOf(substring):返回子字符串在原字符串中首次出现的索引,如果没有找到,则返回 -1。
  • .lastIndexOf(substring):返回子字符串在原字符串中最后一次出现的索引,如果没有找到,则返回 -1。
  • .match(regexp):使用正则表达式与字符串进行匹配。
  • .repeat(count):将字符串重复指定次数后返回。
  • .replace(searchFor, replaceWith):替换与搜索模式匹配的子串。
  • .search(regexp):执行正则表达式搜索。
  • .slice(startIndex, endIndex):提取字符串的一部分并返回新字符串。
  • .split(separator, limit):使用指定的分隔符将字符串分割成数组。
  • .substring(startIndex, endIndex):返回位于两个指定索引之间的字符。
  • .toLowerCase():将字符串转换为小写形式。
  • .toUpperCase():将字符串转换为大写形式。
  • .trim():从字符串的两端删除空白字符。
  • .valueOf():返回 String 对象的原始值。

模板字符串

ES6 引入了模板字符串,提供了创建包含变量和表达式的字符串的简便语法。模板字符串使用反引号包围,并通过 ${expression} 插入变量或表达式:

let name = "Alice";

let greeting = `Hello, ${name}!`;

console.log(greeting); // 输出: 'Hello, Alice!'

模板字符串还支持多行文本,无需使用连接符或特殊字符:

let multiLineString = `This is a string

that spans multiple

lines.`;

console.log(multiLineString);

字符串不可变性

在 JavaScript 中,字符串是不可变的,这意味着一旦创建,字符串的内容就不能被改变。任何看似修改字符串的操作实际上都是创建了一个新的字符串。

类型转换

通常,当你使用字符串方法时,如果你对一个字符串字面量(而不是 String 对象)使用方法,JavaScript 会自动将字面量转换为 String 对象,以便可以调用相应的方法。完成方法调用后,结果通常是一个原始字符串,而不是 String 对象。这是因为 JavaScript 在内部进行了自动装箱和拆箱操作。

字符串比较

在 JavaScript 中,可以使用比较运算符(==、===、!=、!==、<、> 等)来比较字符串。这些比较是基于标准的字典顺序,使用字符的 Unicode 值来进行比较。

console.log("a" < "b"); // 输出: true

console.log("hello" === "hello"); // 输出: true

字符串和数组之间的转换

  • 使用 .split(separator) 方法可以将字符串分割成数组。
  • 使用 .join(separator) 方法可以将数组元素合并成一个字符串。

let str = "apple,banana,cherry";

let fruits = str.split(","); // ['apple', 'banana', 'cherry']

let fruitsString = fruits.join(", "); // 'apple, banana, cherry'

字符串编码

JavaScript 使用 Unicode 字符集。.charCodeAt(index) 和 .codePointAt(index) 方法可以用来获取字符串中特定位置字符的 Unicode 编码。相对的,String.fromCharCode(code) 和 String.fromCodePoint(code) 可以将 Unicode 编码转换回字符串。

国际化

Intl 对象和 String.prototype.localeCompare() 方法提供了基于语言环境的字符串比较、数字格式化和日期时间格式化。

console.log("ä".localeCompare("z", "de")); // 输出: -1,因为在德语中 'ä' 在 'z' 之前

正则表达式

字符串可以与正则表达式一起使用,以执行复杂的搜索和替换操作。例如,.match(regexp) 方法可以找到字符串中与正则表达式匹配的所有子串。

let text = "The rain in SPAIN stays mainly in the plain";

let result = text.match(/ain/g); // 输出: ['ain', 'ain', 'ain']

安全性

当处理来自用户的输入时,应该注意避免安全漏洞,如跨站脚本攻击(XSS)。在将用户输入插入到页面之前,应该对其进行适当的转义。

性能

对于大量的字符串操作,如拼接,使用数组的 .join() 方法通常比使用 + 或 += 操作符更高效。这是因为字符串的不可变性意味着每次使用 + 或 += 时,实际上都会创建一个新的字符串,这可能导致不必要的内存消耗和性能损失。

☆Object 对象

JavaScript 中的 Object 对象是一个基础构造函数,几乎所有的 JavaScript 对象都是 Object 的实例或继承自 Object。以下是关于 Object 对象的一些重要方面:

创建对象

在 JavaScript 中,有几种方式可以创建对象:

  1. 对象字面量:
  2. let person = { name: "Alice", age: 25 };
  3. 使用 new Object():
  4. let person = new Object();
  5. person.name = "Alice";
  6. person.age = 25;
  7. 使用构造函数:
  8. function Person(name, age) {
  9.   this.name = name;
  10.   this.age = age;
  11. }
  12. let person = new Person("Alice", 25);
  13. 使用 Object.create():
  14. let person = Object.create(proto); // 'proto' 是新创建对象的原型对象

Object 属性和方法

Object 提供了多种静态方法来处理对象:

  • Object.assign(target, ...sources):将一个或多个源对象的可枚举属性复制到目标对象。
  • Object.create(proto, [propertiesObject]):创建一个新对象,使用现有的对象来提供新创建的对象的 __proto__。
  • Object.defineProperty(obj, prop, descriptor):在对象上定义新属性或修改现有属性。
  • Object.defineProperties(obj, props):在对象上定义多个属性。
  • Object.entries(obj):返回一个给定对象自身可枚举属性的键值对数组。
  • Object.freeze(obj):冻结对象,使对象不可修改。
  • Object.getOwnPropertyDescriptor(obj, prop):获取对象特定属性的属性描述符。
  • Object.getOwnPropertyDescriptors(obj):获取对象所有自身属性的描述符。
  • Object.getOwnPropertyNames(obj):返回一个数组,包含对象所有自身属性的名称(不包括 Symbol 属性)。
  • Object.getOwnPropertySymbols(obj):返回一个数组,包含对象所有自身的 Symbol 属性。
  • Object.getPrototypeOf(obj):返回指定对象的原型。
  • Object.is(value1, value2):比较两个值是否相同。
  • Object.isExtensible(obj):判断对象是否可扩展。
  • Object.isFrozen(obj):判断对象是否已冻结。
  • Object.isSealed(obj):判断对象是否已密封。
  • Object.keys(obj):返回一个数组,包含对象自身的所有可枚举属性名称。
  • Object.preventExtensions(obj):防止对象扩展。
  • Object.seal(obj):密封对象,阻止添加新属性并将所有现有属性标记为不可配置。
  • Object.setPrototypeOf(obj, prototype):设置对象的原型(即内部 [[Prototype]] 属性)。
  • Object.values(obj):返回一个数组,包含对象自身的所有可枚举属性值。

原型链

JavaScript 对象有一个称为原型的内部属性,对象从其原型继承属性和方法。原型本身也是一个对象,因此原型可能也有自己的原型,这样就形成了一个原型链。当访问对象的属性时,如果对象本身没有这个属性,JavaScript会沿着原型链向上查找,直到找到该属性或达到原型链的顶端(通常是 Object.prototype),如果在原型链中没有找到该属性,则返回 undefined。

原型继承

在 JavaScript 中,继承是通过原型链实现的。当一个函数被创建时,JavaScript 引擎会为这个函数添加一个 prototype 属性,指向一个原型对象。当使用 new 关键字创建一个新对象时,这个新对象内部的 [[Prototype]] 隐藏属性会被赋值为构造函数的 prototype 属性。这样,新对象就可以访问原型对象上的属性和方法。

例如:

function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function() {
  console.log(`${this.name} makes a noise.`);
};

function Dog(name) {
  Animal.call(this, name); // 调用父构造函数,并将 this 绑定到当前对象
}
Dog.prototype = Object.create(Animal.prototype); // 设置 Dog 的原型为 Animal 的实例
Dog.prototype.constructor = Dog; // 设置构造函数为 Dog

Dog.prototype.bark = function() {
  console.log(`${this.name} barks.`);
};

let dog = new Dog('Rex');
dog.speak(); // Rex makes a noise.
dog.bark(); // Rex barks.

在这个例子中,Dog 继承了 Animal。通过设置 Dog.prototype 为 Animal.prototype 的实例,Dog 的实例就可以访问 Animal 原型上的 speak 方法。同时,我们也给 Dog 添加了一个新的方法 bark。

属性描述符

在 JavaScript 中,对象的属性有一些内部特性,这些特性定义了属性的行为。这些特性可以通过属性描述符来控制。属性描述符有两种类型:数据描述符和存取描述符。

  • 数据描述符 有两个可选键:
    • value:属性的值。
    • writable:如果为 true,属性的值可以被修改。
  • 存取描述符 也有两个可选键:
    • get:一个给属性提供 getter 的方法,当访问属性时调用此方法。
    • set:一个给属性提供 setter 的方法,当属性值被修改时调用此方法。

属性描述符还有两个通用键:

  • configurable:如果为 true,该属性的描述符可以被修改,且该属性可以从对应的对象上删除。
  • enumerable:如果为 true,该属性会出现在对象的枚举属性中。

例如,可以使用 Object.defineProperty() 来定义或修改属性及其描述符:

let obj = {};
Object.defineProperty(obj, 'property1', {
  value: 42,
  writable: false,
  enumerable: true,
  configurable: true
});

在这个例子中,obj 对象有一个名为 property1 的属性,其值为 42,不可写(即不可修改),可枚举,且可配置。

不可变性

在 JavaScript 中,不可变性是指对象的状态无法被改变。虽然 JavaScript 中的原始数据类型(如数字、字符串、布尔值等)是不可变的,但对象和数组默认是可变的。不过,你可以采取一些措施来模拟不可变性。

Object.freeze()

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象之后,不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、或者可写性,以及不能修改已有属性的值。此外,冻结一个对象的原型也不能被修改。Object.freeze() 返回和传入的参数相同的对象。

const obj = {
  prop: 42
};

Object.freeze(obj);

obj.prop = 33;
// 尝试修改冻结对象的属性不会有任何效果
console.log(obj.prop); // 输出 42

Object.seal()

Object.seal() 方法可以封闭一个对象,阻止添加新属性同时将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以被改变。

const obj = {
  prop: 42
};

Object.seal(obj);

obj.prop = 33;
obj.newProp = 'test';
// 可以修改现有属性的值,但不能添加新属性
console.log(obj.prop); // 输出 33
console.log(obj.newProp); // undefined,因为添加新属性无效

Object.preventExtensions()

Object.preventExtensions() 方法可以让一个对象变得不可扩展,也就是永远不能再添加新的属性。

const obj = {
  prop: 42
};

Object.preventExtensions(obj);

obj.prop = 33;
obj.newProp = 'test';
// 可以修改现有属性的值,但不能添加新属性
console.log(obj.prop); // 输出 33
console.log(obj.newProp); // undefined,因为添加新属性无效
 

对象控制方法

除了上述的 Object.freeze(), Object.seal(), 和 Object.preventExtensions(),JavaScript 还提供了一些方法来检查对象的不可变性状态:

  • Object.isFrozen() 检查一个对象是否被冻结。
  • Object.isSealed() 检查一个对象是否被封闭。
  • Object.isExtensible() 检查一个对象是否是可扩展的。

这些方法可以帮助你了解对象的当前状态,并根据需要进行相应的操作。不过,需要注意的是,这些不可变性方法并不是深度的,它们只影响对象本身的直接属性。如果对象的属性值是另一个对象,那么这个嵌套的对象的属性是可以被修改的,除非它也被冻结或封闭。

猜你喜欢

转载自blog.csdn.net/cnds123/article/details/134545548
今日推荐