个人技术站点JASONWU

Keep Coding


  • 主页

  • 文章

  • 搜索

JavaScript OOP:原型链

新建: 2021-06-01 编辑: 2025-07-26   |   分类: JavaScript   | 字数: 1669 字

JS OOP(Object-Oriented Programming)的实现原理及方式。

原型继承

JS 中的 OOP 与 Java 不同,JS 中没有真正意义上的类,它是通过原型(Prototype)实现 OOP。

面向对象的四大基本特征:抽象(Abstraction)、封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism)在 JS OOP 中和其他语言没有任何区别。

原型继承(Prototypal Inheritance)
原型对象的所有属性和方法都可以被链接到它的对象访问。

JS 中实现原型继承有三种方式:

  • 构造函数
    • 使用普通函数创建对象,然后指定原型
    • JS 最早实现 OOP 的方式
  • ES6 Class
    • 现代 JS 创建对象的方式,但它仅仅是构造函数的“语法糖”
  • Object.create()
    • 将现有对象作为原型对象,从而创建一个新对象(空对象 {})

构造函数

构造函数与普通函数的唯一区别:构造函数使用 new 操作符调用。

由于箭头函数没有自己的 this 关键字,因此箭头函数不能作为构造函数,也不能用于作为原型对象的方法。

创建对象(错误示例)

JavaScript
 1const User = function (name, age) {
 2  // 实例属性(Instance properties)
 3  this.name = name;
 4  this.age = age;
 5
 6  // 这是错误的,不要在构造函数中定义方法!!!
 7  // 这会导致每个实例都有一份方法拷贝,这将严重影响 JS 性能。
 8  // 正确做法应该是使用原型对象的方法!
 9  this.sayHi = function () {
10    console.log(`你好,${this.name}`);
11  }
12};
13
14const jason = new User('Jason', 25);
15jason.sayHi(); // 你好,Jason
16
17console.log(jason instanceof User); // true

原型链

JavaScript
 1const User = function (name, age) {
 2  // 实例属性(Instance properties)
 3  this.name = name;
 4  this.age = age;
 5};
 6
 7User.prototype.type = '测试用户';
 8
 9User.prototype.sayHi = function () {
10  console.log(`你好,${this.name}`);
11};
12
13const jason = new User('Jason', 25);
14
15jason.sayHi(); // 你好,Jason
16console.log(jason.type); // 测试用户
17
18console.log(jason instanceof User); // true
19
20// 检查原型对象
21console.log(User.prototype === jason.__proto__); // true
22console.log(User.prototype.isPrototypeOf(jason)); // true
23console.log(User.prototype.isPrototypeOf(User)); // false
24
25console.log(jason.hasOwnProperty('name')); // true
26console.log(jason.hasOwnProperty('type')); // false
27
28// 查看原型链
29console.log(jason.__proto__);
30// {type: "测试用户", sayHi: ƒ, constructor: ƒ}
31
32console.log(jason.__proto__.__proto__); // 原型链的顶端
33// {constructor: ƒ, hasOwnProperty: ƒ, isPrototypeOf: f, …}
34
35console.log(jason.__proto__.__proto__.__proto__); // null
36
37console.dir(User.prototype.constructor); // User(name, age)
38
39// 探索 DOM 元素的原型链
40console.dir(document.querySelector('body'));

关键字 new 的工作过程:

  1. 创建一个新对象 {}
  2. 调用函数,this = {}
  3. {}(通过 __proto__ 属性)链接到构造函数的 prototype 属性
  4. 函数自动返回 {}
原型链(Prototype Chain)
用于查找原型上的属性和方法。

静态属性和方法

JavaScript
 1const User = function (name, age) {
 2  // 实例属性(Instance properties)
 3  this.name = name;
 4  this.age = age;
 5};
 6
 7// 静态属性和方法是绑定在 User Construct,而非 Prototype Constructor
 8User.version = 'v1.0.0';
 9
10User.info = function () {
11  console.log(`${this.name},开发者:Jason Wu,版本:${User.version}`);
12}
13
14const jason = new User('Jason', 25);
15
16console.log(jason.version); // undefined
17
18console.log(User.version); // v1.0.0
19User.info(); // User,开发者:Jason Wu,版本:v1.0.0

继承与多态

JavaScript
 1const User = function (name, age) {
 2  this.name = name;
 3  this.age = age;
 4};
 5
 6User.prototype.sayHi = function () {
 7  console.log(`你好,${this.name}`);
 8};
 9
10const Vip = function (name, age, level) {
11  // 1. 使用父类构造函数
12  User.call(this, name, age);
13
14  this.level = level;
15};
16
17// 2. 链接原型对象
18Vip.prototype = Object.create(User.prototype);
19
20// 3. 修正原型对象的构造函数
21// console.log(Vip.prototype.constructor); // `User` 函数
22Vip.prototype.constructor = Vip;
23// console.log(Vip.prototype.constructor); // `Vip` 函数
24
25Vip.prototype.sayHi = function () {
26  console.log(`用户:${this.name},VIP 等级:${this.level}`);
27};
28
29const jason = new Vip('Jason', 25, '3');
30
31jason.sayHi(); // 用户:Jason,VIP 等级:3
32
33// 检查原型链
34console.log(jason instanceof Vip); // true
35console.log(jason instanceof User); // true
36console.log(jason instanceof Object); // true

Object.create()

JavaScript
 1const userProto = {
 2  init(name, age) {
 3    this.name = name;
 4    this.age = age;
 5  },
 6
 7  sayHi() {
 8    console.log(`你好,${this.name}`);
 9  }
10};
11
12// 使用已有对象为原型对象从而创建一个新的空对象
13const jason = Object.create(userProto);
14
15jason.init('Jason', 25);
16jason.sayHi(); // 你好,Jason
17
18// 检查原型对象
19console.log(jason.__proto__ === userProto); // true

继承与多态

JavaScript
 1const userProto = {
 2  init(name, age) {
 3    this.name = name;
 4    this.age = age;
 5  },
 6
 7  sayHi() {
 8    console.log(`你好,${this.name}`);
 9  }
10};
11
12// 1. 创建新的原型对象
13const vipProto = Object.create(userProto);
14
15vipProto.init = function (name, age, level) {
16  // 2. 使用父类构造函数
17  userProto.init.call(this, name, age);
18
19  this.level = level;
20}
21
22vipProto.sayHi = function () {
23  console.log(`用户:${this.name},VIP 等级:${this.level}`);
24};
25
26const jason = Object.create(vipProto);
27
28jason.init('Jason', 25, 3);
29jason.sayHi(); // 用户:Jason,VIP 等级:3
30
31// 检查原型链
32console.dir(jason);
#OOP#

文章:JavaScript OOP:原型链

链接:https://www.wuxianjie.net/posts/js-oop/

作者:吴仙杰

文章: 本博客文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议,转载请注明出处!

JavaScrip OOP:ES6 Class
JavaScript 使用 Promise:Async/Await
  • 文章目录
  • 站点概览
吴仙杰

吴仙杰

🔍 Ctrl+K / ⌘K

27 文章
9 分类
25 标签
邮箱 GitHub
  • 原型继承
  • 构造函数
    • 创建对象(错误示例)
    • 原型链
    • 静态属性和方法
    • 继承与多态
  • Object.create()
    • 继承与多态
© 2021-2025 吴仙杰 保留所有权利 All Rights Reserved
浙公网安备 33010302003726号 浙ICP备2021017187号-1
0%