JavaScript 中的 Promise 与原型链详解

68 阅读3分钟

JavaScript 中的 Promise 与原型链详解

在 JavaScript 中,Promise 和原型链是两个核心概念。Promise 为异步编程提供了优雅的解决方案,而原型链则是 JavaScript 实现面向对象编程的基础。本文将结合具体代码示例,详细解析这两个概念。

一、Promise:异步编程的利器

Promise 是 ES6 引入的异步编程解决方案,它可以有效解决回调地狱问题,让异步代码的逻辑更清晰。

1. Promise 的基本概念

  • 状态:Promise 有三种状态,分别是pending(等待中)、fulfilled(已成功)、rejected(已失败)。状态一旦改变就不可逆。
  • ** executor 函数 **:创建 Promise 实例时传入的函数,会立即执行,用于定义异步操作。
  • 方法then()(处理成功状态)、catch()(处理失败状态)、finally()(无论成功失败都会执行)。

2. Promise 代码解析

以下是 Promise 的示例代码及详细解释:

<script>
// 创建Promise实例p
const p = new Promise((resolve, reject) => {
    // executor函数会立即执行
    console.log(111); // 立即打印111
    // 模拟异步耗时任务(1秒后执行)
    setTimeout(() => {
        console.log(333); // 1秒后打印333
        reject('错误1'); // 将状态改为rejected,传递错误信息
        // resolve('结果1'); // 若调用此句,状态改为fulfilled,传递成功结果
    }, 1000);
})
console.log(222); // 打印222(在setTimeout之前执行,因为setTimeout是异步)
console.log(p,'////'); // 打印Promise实例(此时状态为pending)
console.log(p.__proto__ == Promise.prototype); // 打印true(实例的__proto__指向构造函数的prototype)
console.log(p.__proto__); // 打印Promise的原型对象

// 处理Promise结果(异步执行)
p.then((data) => {
    // 当状态为fulfilled时执行,接收resolve传递的数据
    console.log(data);
}).catch(err => {
    // 当状态为rejected时执行,接收reject传递的错误
    console.log(err); // 此处会打印'result1'
}).finally(() => {
    // 无论成功失败都会执行
    console.log('finally'); // 打印'finally'
})
</script>

执行顺序说明

  1. 执行new Promise时,立即调用 executor 函数,打印111
  2. 遇到setTimeout,将其回调放入异步队列,继续执行同步代码
  3. 打印222和 Promise 实例(此时状态为pending
  4. 1 秒后,执行setTimeout回调:打印333,调用reject将状态改为rejected
  5. 触发catch方法,打印错误1
  6. 最后执行finally,打印finally

image.png

二、原型链:JavaScript 面向对象的基石

JavaScript 的面向对象并非基于类的血缘关系,而是通过原型链实现的。每个对象都有__proto__属性,指向其原型对象;构造函数有prototype属性,也指向原型对象;原型对象的constructor属性指向构造函数。

1. 原型链代码解析

以下是原型链的示例代码及解释:

// 定义构造函数Person
function Person(name, age) {
    this.name = name; // 实例属性name
    this.age = age; // 实例属性age
}

// 给Person的原型对象添加属性species
Person.prototype.species = '人类';

// 创建Person实例zhen
let zhen = new Person('郑总', 18);
console.log(zhen.species); // 打印'人类'(通过原型链访问到Person.prototype上的species)

// 定义一个普通对象kong
const kong = {
    name: '孔子',
    hobbies: ['读书', '喝酒']
}

// 修改zhen的__proto__指向kong(改变原型链)
zhen.__proto__ = kong;
// 此时zhen的原型链指向kong,而非Person.prototype
console.log(zhen.hobbies); // 打印['读书', '喝酒'](访问kong的hobbies)
console.log(zhen.species); // 打印undefined(kong上没有species属性,且原型链中也没有)

原型链查找规则

  • 当访问对象的属性时,先在对象自身查找,若找不到则通过__proto__查找原型对象
  • 若原型对象中也没有,则继续查找原型对象的__proto__,直到null
  • 上例中,修改zhen.__proto__ = kong后,原型链指向改变,因此无法再访问Person.prototype上的species

image.png

三、总结

  1. Promise

    • 是 ES6 的异步解决方案,通过状态管理简化异步逻辑
    • 核心是pendingfulfilled/rejected的状态变化,以及then/catch/finally的链式调用
  2. 原型链

    • JavaScript 面向对象的基础,通过__proto__串联对象与原型
    • 实例的__proto__指向构造函数的prototype,原型对象的constructor指向构造函数