JavaScript中的原型和原型链怎么理解

发布时间:2022-01-04 11:03:36 作者:iii
来源:亿速云 阅读:103
# JavaScript中的原型和原型链怎么理解

## 引言

JavaScript作为一门基于原型的语言,原型(Prototype)和原型链(Prototype Chain)是其核心概念之一。理解原型和原型链对于掌握JavaScript的面向对象编程、继承机制以及代码设计模式至关重要。本文将深入探讨原型和原型链的概念、工作原理以及实际应用。

---

## 1. 什么是原型?

### 1.1 原型的定义

在JavaScript中,每个对象(除了`null`)都有一个与之关联的原型对象(Prototype Object)。原型对象可以看作是对象的“模板”,它定义了对象的共享属性和方法。

### 1.2 如何访问原型?

- **`__proto__`属性**(非标准,但被广泛支持):  
  通过对象的`__proto__`属性可以直接访问其原型对象。  
  例如:
  ```javascript
  const obj = {};
  console.log(obj.__proto__); // 输出: Object.prototype

1.3 构造函数与原型

每个构造函数(如ObjectArrayFunction等)都有一个prototype属性,指向其原型对象。
例如:

function Person(name) {
  this.name = name;
}
console.log(Person.prototype); // 输出: Person的原型对象

当通过构造函数创建实例时,实例的__proto__会指向构造函数的prototype对象:

const person1 = new Person("Alice");
console.log(person1.__proto__ === Person.prototype); // true

2. 原型链的概念

2.1 原型链的定义

原型链是由对象的原型对象通过__proto__链接起来的一条链式结构。当访问一个对象的属性或方法时,JavaScript引擎会沿着原型链向上查找,直到找到该属性或到达原型链的顶端(Object.prototype__proto__null)。

2.2 原型链的示例

function Animal(name) {
  this.name = name;
}
Animal.prototype.eat = function() {
  console.log(`${this.name} is eating.`);
};

function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {
  console.log("Woof!");
};

const dog1 = new Dog("Buddy", "Golden Retriever");
dog1.eat(); // 输出: Buddy is eating.
dog1.bark(); // 输出: Woof!

上述代码的原型链关系如下: 1. dog1.__proto__指向Dog.prototype。 2. Dog.prototype.__proto__指向Animal.prototype。 3. Animal.prototype.__proto__指向Object.prototype。 4. Object.prototype.__proto__null

2.3 原型链的查找机制

当调用dog1.eat()时: 1. 首先检查dog1自身是否有eat方法(没有)。 2. 沿着原型链查找Dog.prototype(没有)。 3. 继续查找Animal.prototype,找到eat方法并调用。


3. 原型与继承

3.1 基于原型的继承

JavaScript通过原型链实现继承。子类的原型对象指向父类的实例,从而继承父类的属性和方法。

示例:组合继承(经典继承)

function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log(`Hello, ${this.name}!`);
};

function Child(name, age) {
  Parent.call(this, name); // 继承属性
  this.age = age;
}
Child.prototype = Object.create(Parent.prototype); // 继承方法
Child.prototype.constructor = Child; // 修复构造函数指向

const child1 = new Child("Tom", 10);
child1.sayHello(); // 输出: Hello, Tom!

3.2 ES6的class语法糖

ES6引入了class关键字,但其底层仍然是基于原型的继承。

class Parent {
  constructor(name) {
    this.name = name;
  }
  sayHello() {
    console.log(`Hello, ${this.name}!`);
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name);
    this.age = age;
  }
}

const child1 = new Child("Tom", 10);
child1.sayHello(); // 输出: Hello, Tom!

4. 原型链的常见问题

4.1 修改原型的影响

修改构造函数的原型会影响所有实例:

function Person() {}
const person1 = new Person();
Person.prototype.sayHi = function() {
  console.log("Hi!");
};
person1.sayHi(); // 输出: Hi!

4.2 属性遮蔽(Property Shadowing)

如果实例和原型链上有同名属性,实例属性会遮蔽原型属性:

function Person() {}
Person.prototype.name = "Unknown";
const person1 = new Person();
person1.name = "Alice";
console.log(person1.name); // 输出: Alice(遮蔽了原型属性)

4.3 原型链的终点

所有原型链的终点是Object.prototype,其__proto__null

console.log(Object.prototype.__proto__); // null

5. 实际应用场景

5.1 方法共享

通过原型共享方法,节省内存:

function Car(model) {
  this.model = model;
}
Car.prototype.drive = function() {
  console.log(`${this.model} is driving.`);
};
const car1 = new Car("Toyota");
const car2 = new Car("BMW");
car1.drive(); // Toyota is driving.
car2.drive(); // BMW is driving.

5.2 扩展内置对象

通过修改原型扩展内置对象的功能(需谨慎):

Array.prototype.last = function() {
  return this[this.length - 1];
};
const arr = [1, 2, 3];
console.log(arr.last()); // 3

5.3 实现多态

通过原型链实现多态行为:

function Animal() {}
Animal.prototype.makeSound = function() {
  console.log("Some sound");
};

function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.makeSound = function() {
  console.log("Woof!");
};

const animal = new Animal();
const dog = new Dog();
animal.makeSound(); // Some sound
dog.makeSound(); // Woof!

6. 总结

理解原型和原型链是掌握JavaScript面向对象编程的关键,希望本文能帮助你深入理解这一核心概念! “`

这篇文章总计约3500字,涵盖了原型和原型链的核心概念、工作原理、实际应用以及常见问题。内容结构清晰,适合初学者和有一定基础的开发者阅读。

推荐阅读:
  1. JavaScript中原型和原型链是什么
  2. javascript原型和原型链

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

javascript

上一篇:XEffects Social Media Mac工具有什么用

下一篇:JS的script标签属性有哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》