【JavaScript原型链prototype详解】

简介: 在JavaScript中,每个对象都有一个原型(prototype)属性,它指向另一个对象。这个被指向的对象也有自己的原型,以此类推,最终形成了一个原型链。原型链的顶端是Object.prototype,它是所有对象的根原型。当我们访问一个对象的属性时,如果该对象自身没有这个属性,JavaScript会沿着原型链向上查找,直到找到匹配的属性或者到达原型链的末端。

8e6a582dee8e44f99ee653c2a97688a3.png

1.什么是JavaScript原型链

在JavaScript中,每个对象都有一个原型(prototype)属性,它指向另一个对象。这个被指向的对象也有自己的原型,以此类推,最终形成了一个原型链。原型链的顶端是Object.prototype,它是所有对象的根原型。

当我们访问一个对象的属性时,如果该对象自身没有这个属性,JavaScript会沿着原型链向上查找,直到找到匹配的属性或者到达原型链的末端。

2.JavaScript原型链的工作原理

JavaScript原型链的工作原理非常简单:当我们访问一个对象的属性时,如果该对象本身没有这个属性,那么JavaScript就会沿着原型链向上查找。这个过程会一直持续到找到匹配的属性或者到达原型链的末端。

这里有一个很简单的例子来说明原型链的工作原理:

2. 
// 定义一个人类构造函数
function Person(name, age) {
   
   
    this.name = name;
    this.age = age;
}

// 添加一个打招呼的方法
Person.prototype.greet = function() {
   
   
    console.log(`Hi, my name is ${
     
     this.name} and I'm ${
     
     this.age} years old.`);
};

// 创建一个人类实例
const person = new Person('John', 30);

// 访问person的name属性,输出"John"
console.log(person.name);

// 访问person的greet方法,输出"Hi, my name is John and I'm 30 years old."
person.greet();

在这个例子中,我们创建了一个Person构造函数,并且给它的原型对象添加了一个greet方法。当我们使用new关键字创建一个person实例时,它会继承Person构造函数的原型对象上的greet方法。

因为person对象本身并没有greet方法,所以JavaScript会沿着原型链向上查找直到找到匹配的方法。

3.创建对象的多种方式

在JavaScript中,我们有多种方式可以创建对象。根据不同的创建方式,JavaScript对象的原型链也会有所不同。

1. 字面量方式创建对象

使用字面量方式创建对象的原型是Object.prototype,即所有字面量创建的对象都是Object的实例。

// 创建一个空对象 
const emptyObj = {
   
   };
// 创建一个带有属性和方法的对象 
const obj = {
   
   
    name: 'John',
    age: 30,
    greet() {
   
   
        console.log(`Hi, my name is ${
     
     this.name} and I'm ${
     
     this.age} years old.`);
    }
};

2. 构造函数方式创建对象

使用构造函数方式创建对象的原型是构造函数的原型对象(prototype)。

// 定义一个人类构造函数 
function Person(name, age) {
   
   
    this.name = name;
    this.age = age;
}
// 添加一个打招呼的方法 
Person.prototype.greet = function () {
   
   
    console.log(`Hi, my name is ${
     
     this.name} and I'm ${
     
     this.age} years old.`);
};
// 创建一个人类实例 
const person = new Person('John', 30);

在这个例子中,我们使用构造函数方式创建了一个Person对象。当我们使用new关键字创建一个person实例时,它会继承Person构造函数的原型对象上的greet方法。

3. Class方式创建对象

在ES6中引入了class关键字,使得JavaScript中的类和继承更加易于理解和使用。虽然底层仍然基于原型链机制,但这种语法糖简化了对象和继承的创建过程。

class Person {
   
   
    constructor(name, age) {
   
   
      this.name = name;
      this.age = age;
    }

    greet() {
   
   
      console.log(`Hi, my name is ${
     
     this.name} and I'm ${
     
     this.age} years old.`);
    }
  }

  const person = new Person('John', 30);

Class方式创建的对象和构造函数方式创建的对象一样,其原型是Class构造函数的prototype属性所指向的对象。

4.修改原型与继承

通过修改原型,我们可以实现对象之间的继承关系。当一个对象的原型发生改变时,它的原型链也会相应地改变。这样一来,对象可以从其原型链上继承属性和方法,实现代码的重用和扩展。

// 定义一个动物类构造函数
function Animal(legs) {
   
   
    this.legs = legs;
}

// 添加一个移动的方法
Animal.prototype.move = function() {
   
   
    console.log('Moving...');
};

// 定义一个鸟类构造函数
function Bird(name, legs) {
   
   
    this.name = name;
    Animal.call(this, legs); // 调用父类构造函数,继承父类属性
}

// 继承父类方法
Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Bird;

// 添加一个飞行的方法
Bird.prototype.fly = function() {
   
   
    console.log('Flying...');
};

const bird = new Bird('Pigeon', 2);
console.log(bird.name); // Pigeon
console.log(bird.legs); // 2
bird.move(); // Moving...
bird.fly(); // Flying...

这里我们定义了一个Animal构造函数,它有一个move方法。然后我们定义了一个Bird构造函数,并通过Object.create方法继承了Animal构造函数的原型对象,从而实现了对move方法的继承。最后我们添加了一个fly方法并创建了一个bird对象。

5.JavaScript原型链的性能和优化

原型链在JavaScript中的运作会带来一定的性能开销。在访问属性时,查找过程需要沿着原型链逐级查找,直到找到属性或者到达原型链末端。因此,过深的原型链结构可能导致性能下降。为了优化性能,可以合理设计对象的原型链,避免过于庞大和复杂的结构。

6.JavaScript原型链的扩展内容

深入了解原型链的实现细节,包括[[Prototype]]属性、proto属性和Object.getPrototypeOf()方法的使用。
介绍原型链在函数和构造函数中的应用,以及原型链在函数原型扩展和方法继承中的运用。
讨论原型链与作用域链之间的关系,解释为什么可以在原型对象中访问全局变量。
探讨Object.create()方法和Object.setPrototypeOf()方法在原型链操作中的应用场景。
引用一些优秀的资源和文章,如MDN文档、JavaScript权威指南等,供读者深入学习和进一步扩展知识。

总结

通过深入了解JavaScript原型链的概念、工作原理和应用,我们可以更好地理解JavaScript面向对象编程的机制。原型链不仅是JavaScript中继承和属性查找的基础,还能够帮助我们深入理解JavaScript语言的设计思想。通过合理地应用原型链,我们可以创建高效、可扩展的前端代码。

目录
相关文章
|
2月前
|
JavaScript 前端开发 开发者
理解JavaScript中的原型链:基础与实践
【10月更文挑战第8天】理解JavaScript中的原型链:基础与实践
|
1月前
|
JavaScript 前端开发
JavaScript 原型链的实现原理是什么?
JavaScript 原型链的实现原理是通过构造函数的`prototype`属性、对象的`__proto__`属性以及属性查找机制等相互配合,构建了一个从对象到`Object.prototype`的链式结构,实现了对象之间的继承、属性共享和动态扩展等功能,为 JavaScript 的面向对象编程提供了强大的支持。
|
1月前
|
JavaScript 前端开发
原型链在 JavaScript 中的作用是什么?
原型链是 JavaScript 中实现面向对象编程的重要机制之一,它为代码的组织、复用、扩展和多态性提供了强大的支持,使得 JavaScript 能够以简洁而灵活的方式构建复杂的应用程序。深入理解和熟练运用原型链,对于提升 JavaScript 编程能力和开发高质量的应用具有重要意义。
|
1月前
|
JavaScript 前端开发
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
|
2月前
|
JavaScript 前端开发 开发者
探索JavaScript原型链:深入理解与实战应用
【10月更文挑战第21天】探索JavaScript原型链:深入理解与实战应用
33 1
|
2月前
|
JavaScript 前端开发 开发者
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
30 0
|
2月前
|
JavaScript 前端开发 开发者
原型链深入解析:JavaScript中的核心机制
【10月更文挑战第13天】原型链深入解析:JavaScript中的核心机制
38 0
|
2月前
|
JavaScript 前端开发 安全
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
30 0
|
2月前
|
JavaScript 前端开发
JavaScript - 测试 Prototype
JavaScript - 测试 Prototype
16 0
|
3月前
|
JavaScript 前端开发
JavaScript prototype(原型对象)
JavaScript prototype(原型对象)
36 0