JS原型继承

原型继承

在 JavaScript 中,原型继承(Prototype Inheritance)是一种对象通过另一个对象继承属性和方法的机制。JavaScript 是基于原型的语言,这意味着对象可以从其他对象继承属性,而不是通过类继承。下面是关于 JavaScript 原型继承的详细介绍:

1. 什么是原型(Prototype)

在 JavaScript 中,每个对象都有一个关联的内部属性,称为 [[Prototype]]。这个 [[Prototype]] 是另一个对象,如果在当前对象中没有找到某个属性或方法,JavaScript 会在其 [[Prototype]] 对象中查找。这个链式的继承关系被称为原型链(prototype chain)。

2. 创建对象的原型继承
通过构造函数实现原型继承
// 定义一个构造函数
function Animal(name) {
    this.name = name;
}

// 在 Animal 的原型上添加一个方法
Animal.prototype.speak = function() {
    console.log(`${this.name} makes a noise.`);
};

// 创建一个新的对象实例
let animal = new Animal('Dog');
animal.speak(); // 输出: Dog makes a noise.

在上面的例子中,Animal 构造函数创建的所有对象都共享 Animal.prototype 上的方法 speak。如果在对象实例 animal 上找不到 speak 方法,它会在其原型链上查找。

继承另一个对象的属性和方法
// 定义一个构造函数
function Dog(name, breed) {
    Animal.call(this, name); // 调用父类构造函数
    this.breed = breed;
}

// 设置 Dog 的原型为 Animal 的一个实例
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

// 在 Dog 的原型上添加一个方法
Dog.prototype.bark = function() {
    console.log(`${this.name} barks.`);
};

let myDog = new Dog('Rex', 'German Shepherd');
myDog.speak(); // 输出: Rex makes a noise.
myDog.bark();  // 输出: Rex barks.

在这个例子中,Dog 继承了 Animal 的属性和方法。Object.create(Animal.prototype) 创建了一个新的对象,这个对象的 [[Prototype]] 指向 Animal.prototype。因此,Dog.prototypeAnimal.prototype 的一个实例,Dog 的实例可以访问 Animal 的方法。

3. 使用 Object.create 进行继承

Object.create() 方法可以创建一个新对象,并将其原型设置为指定的对象。

let animal = {
    speak: function() {
        console.log(`${this.name} makes a noise.`);
    }
};

let dog = Object.create(animal);
dog.name = 'Buddy';
dog.speak(); // 输出: Buddy makes a noise.

在这个例子中,dog 对象继承了 animal 对象的 speak 方法。Object.create() 方法为原型继承提供了一种简单而强大的方法。

4. 原型链

JavaScript 中的对象是通过原型链来查找属性的。如果一个对象自身没有某个属性,那么 JavaScript 引擎会沿着原型链向上查找,直到找到该属性或达到链的顶端(通常是 null)。

function Person(name) {
    this.name = name;
}

Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name}`);
};

let person1 = new Person('Alice');
let person2 = new Person('Bob');

person1.greet(); // 输出: Hello, my name is Alice
person2.greet(); // 输出: Hello, my name is Bob

console.log(person1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true

在这个例子中:

  • person1.__proto__ 指向 Person.prototype
  • Person.prototype.__proto__ 指向 Object.prototype

这就是原型链的基本概念。

5. class 语法糖

ES6 引入了 class 语法,这实际上是基于原型的继承的一种语法糖,使得定义和继承类更加直观和简洁。

class Animal {
    constructor(name) {
        this.name = name;
    }

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

class Dog extends Animal {
    constructor(name, breed) {
        super(name); // 调用父类的构造函数
        this.breed = breed;
    }

    bark() {
        console.log(`${this.name} barks.`);
    }
}

let myDog = new Dog('Rex', 'German Shepherd');
myDog.speak(); // 输出: Rex makes a noise.
myDog.bark();  // 输出: Rex barks.

使用 classextends 关键字可以更清晰地表达继承关系,底层仍然是基于原型链的实现。

小结

  • JavaScript 的原型继承允许对象从其他对象继承属性和方法。
  • 每个对象都有一个 [[Prototype]],用来实现属性和方法的继承。
  • 可以通过构造函数和 Object.create() 方法来实现原型继承。
  • ES6 的 class 语法提供了定义类和继承的简洁方式,但其底层仍然基于原型链。
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值