js继承

原型链继承

首先来看下原型和原型链的区别 原型(Prototype)

原型是JavaScript中实现对象继承的核心概念之一。每个JavaScript对象(除了null)都与一个原型对象相关联,这个原型对象通过内部属性[[Prototype]](在旧版JavaScript中可通过__proto__属性访问)与对象建立联系。原型对象本身也是普通的JavaScript对象,它可以有自己的属性和方法。

当试图访问一个对象的属性或方法时,JavaScript引擎首先在该对象自身的属性中查找。如果在当前对象上找不到该属性或方法,引擎会沿着[[Prototype]]链向上查找,直到找到该属性或方法,或者查找到null(即到达原型链的顶端)。这种基于原型的属性和方法查找机制就是所谓的"原型链"。

原型链(Prototype Chain)

原型链是通过对象的[[Prototype]]属性形成的对象间的连接链条。当一个对象的属性或方法在自身定义中未找到时,JavaScript引擎会自动到其原型对象中去查找。如果原型对象还有自己的原型(即[[Prototype]]),那么查找过程会进一步延续到原型的原型,直到找到所需的属性或方法,或者查找到原型链的尽头(null)。

原型与原型链的区别

原型和原型链虽然密切相关,但它们描述的是对象继承机制的不同方面:

  • 原型:特指一个对象直接关联的那个原型对象,它是对象继承属性和方法的直接来源。原型本身是一个普通的JavaScript对象,可以定义属性、方法,也可以有自己的原型(即形成原型链)。

  • 原型链 :是由一个对象与其原型、原型的原型、直至null形成的链式结构。原型链是实现对象属性和方法继承的查找路径,它体现了对象间继承关系的层级结构。

简单来说,原型 是个体对象,是原型链中的一个节点;原型链 则是由这些原型节点通过[[Prototype]]链接起来的整体结构。理解原型和原型链的区别有助于更好地掌握JavaScript的面向对象编程和继承机制。

上图来自JS深入理解原型和原型链以及区别(包含面试题详解) - 掘金 (juejin.cn)

javascript 复制代码
// 1. 定义父类(基类):首先创建一个基础构造函数,如Person,并在其原型(Person.prototype)上定义共享的方法和属性。
function Person(name, age) {
    this.name = name
    this.age = age
}

Person.prototype.sayHello = function () {
    console.log(`Hello, my name is ${this.name}, and I'm ${this.age} years old.`)
}
// 2. 创建子类:定义一个新的构造函数,如Student,并使其原型对象指向父类的一个实例。这样,子类实例就可以通过原型链访问到父类的属性和方法。
function Student(name, age, major) {
    Person.call(name, age)
    this.major = major
}

Student.prototype = Object.create(Person.prototype)
// 修复子类的constructor属性:由于我们直接将子类的原型设置为父类实例,子类的constructor属性不再指向Student,而是指向Person。为了修复这个问题,通常会手动设置回来:
Student.prototype.constructor = Student
// 添加子类特有的方法:在子类的原型上添加专属于子类的方法,这些方法不会影响到父类或其他继承自同一父类的子类。
Student.prototype.sayMajor = function () {
    console.log(`My major is ${this.major}.`)
}
// 使用示例
const student = new Student("Alice", 20, "Computer Science"); 
student.sayHello(); // 输出:Hello, my name is Alice, and I'm 20 years old. student.sayMajor(); // 输出:My major is Computer Science.

Class继承

在JavaScript中,从ES6(ECMAScript 6)开始引入了基于类(Class)的面向对象编程模型,使得创建和继承类变得更加直观和简洁。以下是如何使用class关键字实现类继承的示例:

javascript 复制代码
           // 定义父类(基类)
            class ParentClass {
                constructor(param1, param2) {
                    this.property1 = param1
                    this.property2 = param2
                }

                method1() {
                    console.log('ParentClass.method1 called')
                }
            }

            // 定义子类
            class ChildClass extends ParentClass {
                constructor(param1, param2, childParam) {
                    super(param1, param2) // 调用父类构造函数,传递必要的参数
                    this.childProperty = childParam
                }

                // 继承父类方法并进行覆盖(重写)
                method1() {
                    console.log('ChildClass.method1 called')
                    super.method1() // 调用父类的method1方法
                }

                // 定义子类特有的方法
                childMethod() {
                    console.log('ChildClass.childMethod called')
                }
            }

            // 使用子类
            const childInstance = new ChildClass('value1', 'value2', 'childValue')

            childInstance.method1() // 输出:ChildClass.method1 called
            //       ParentClass.method1 called

            childInstance.childMethod() // 输出:ChildClass.childMethod called
  • 使用class关键字定义类,如class ParentClassclass ChildClass
  • 在父类(ParentClass)中定义构造函数(constructor),用于初始化实例属性。同时,可以定义类的方法(如method1)。
  • 子类(ChildClass)通过extends关键字继承父类。在子类构造函数中,使用super关键字调用父类构造函数,以继承父类的属性。
  • 子类可以覆盖(重写)从父类继承的方法,如method1。在覆盖的方法内部,可以使用super.methodName()调用父类的同名方法。
  • 子类可以定义自己的特有方法,如childMethod
  • 通过new ChildClass(...)创建子类实例,并使用实例调用其方法。

通过这种方式,JavaScript的类继承机制实现了代码复用、层次化的对象结构以及多态等面向对象编程特性。需要注意的是,尽管JavaScript使用了class关键字,但其底层仍然是基于原型链的继承机制。类语法提供了一种更易于理解和使用的封装,简化了面向对象编程的实现。

相关推荐
feixing_fx23 分钟前
告别枯燥字体:Web 字体加载策略与 font-display 最佳实践
前端·css·前端框架·交互·css3
Liora_Yvonne43 分钟前
不懂后端,只会 TypeScript,想独立做完整项目?这套全栈底座就是给前端准备的
前端·后端·全栈
前端Hardy1 小时前
GitHub 爆火!236K+ Star!一套 Skills 让 AI 按工程师方式写代码
前端·后端
烬羽1 小时前
AI Coding 全流程实战:从需求到上线,我用 AI 开发了一个 NPM 包
前端·react.js·ai编程
前进的程序员1 小时前
Codex破局:前端组件秒级生成|提速React/Vue开发,可复用提示词+实战调试经验
前端·vue.js·react.js·codex
前端snow1 小时前
ai agent ---output汇总
前端
4311媒体网1 小时前
帝国CMS网站自定义搭建技巧
服务器·开发语言·前端
JunjunZ1 小时前
Vue 3 文件预览的通用设计与实现
前端·vue.js
CappuccinoRose1 小时前
ES6+ 核心语法糖
前端·es6·解构·可选链·空值合并
两只羊ovo1 小时前
Promise.all 并发请求实战:从串行 await 到双段并行
前端