JavaScript对象-原型

JavaScript对象-原型

JavaScript 中,对象是一种非常重要的数据类型,它是一组包含键值对的数据集合。对象可以存储数据,也可以存储方法,我们可以通过对象的属性和方法来操作对象。

但是,这些属性和方法来自何处?这就要涉及到 JavaScript 中的原型。

什么是原型

对象在 JavaScript 中是通过构造函数创建的,每个构造函数都有一个原型对象,我们可以通过 __proto__ 属性获取它的原型对象。

例如,我们可以用以下代码创建一个构造函数:

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

let person = new Person('小明');
console.log(person.__proto__); // 输出 Person {}

这里,Person 就是一个构造函数,我们用 new 关键字创建了一个 Person 类型的实例 person。可以看到,person.__proto__ 输出了一个空的 Person 构造函数的原型对象。

原型可以被看作是一个模板,包含了构造函数可以使用的属性和方法。当我们访问一个对象属性或方法时,如果它不存在于自身属性上,那 JavaScript 就会在原型链上继续寻找该属性或方法。

原型链

原型对象之间形成一个链式结构,也就是原型链。在原型链中,每个对象都有一个指向其原型对象的 __proto__ 属性。

JavaScript 沿着原型链向上搜索,直到找到请求的成员或方法。如果它找不到指定的成员或方法,则返回 undefined

以下是一个简单的原型链示例:

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

Person.prototype.sayHi = function() {
  console.log(`Hi, my name is {this.name}.`);
};

function Student(name, grade) {
  this.grade = grade;
  Person.call(this, name);
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.sayGrade = function() {
  console.log(`I'm in grade{this.grade}.`);
};

let student = new Student('小明', 6);
student.sayHi();         // 输出 "Hi, my name is 小明。"
student.sayGrade();      // 输出 "I'm in grade 6。"
console.log(student.__proto__);          // 输出 Student.prototype
console.log(student.__proto__.__proto__); // 输出 Person.prototype

在这个例子中,我们定义了一个 Person 构造函数,它有一个 sayHi 方法,在 Student 构造函数中调用 Person 构造函数,然后通过 Object.create() 方法创建了一个 Student 原型对象,并将其指向 Person 的原型对象,最后,我们定义了 Student 自身的方法 sayGrade

person 实例中,我们可以看到 __proto__ 属性指向了 Student.prototype 对象,这是因为 student 的构造函数是 Student。而 Student.prototype__proto__ 属性又指向了 Person.prototype,因为我们采用了继承关系。

prototype 和 __proto__ 的区别

JavaScript 中的每个对象都有一个原型,它都有一个指向原型的 __proto__ 属性。每个构造函数也都有一个 prototype 属性,它所有的实例对象的原型引用了它。 prototype 属性是每个 JavaScript 函数中特有的属性。

先来看 prototype 对象。

  • 函数的 prototype 是一个对象。
  • 但是普通对象没有 prototype 属性,因为 prototype 只属于构造函数。

在 JavaScript 中,每个构造函数都有一个 prototype 对象。这个对象包含添加到该类型所有实例的属性和方法。例如,在以下代码中:

function Person() {}
Person.prototype.name = '小明';

这个 name 属性是 Person 构造函数的所有实例共享的。

接下来,我们来看 __proto__ 属性。

  • __proto__ 是每个 JavaScript 对象都有的属性,它指向该对象的原型对象。
  • __proto__ 属性在 JavaScript 中是一个非标准属性,它被大多数现代浏览器支持。

在以上提到的例子中,person.__proto__ 返回了一个对象,这个对象是 Person 构造函数的原型对象。

使用原型的好处

使用原型有以下几个好处:

  • 原型可以减少内存消耗。当我们创建对象的时候,所有对象都实现了该对象类型的方法和属性。如果使用原型,方法和属性将统一存储在原型对象中,而不会分别存储于每个对象。
  • 当我们需要修改对象类型的方法时,只需要在原型对象中修改一次即可,而不用每一个实例对象中都修改一次。
  • 代码的可读性会更好。将所有与类型相关的信息统一存储在原型对象中,可以使代码更加直观。

总结

原型和原型链是 JavaScript 中非常重要的概念,理解它们对于写出高效、可维护的代码来说至关重要。在代码编写过程中,我们可以使用原型继承我们所需要的方法和属性,从而简化代码。同时,原型也是 JavaScript 最强大的特性之一,它可以提供很多想象力。

谨记:对象的属性和方法可以从原型继承而来,同时也可以在实际拥有这些属性和方法的对象上定义。如果这个对象上定义了这个属性或方法,则 JavaScript 不会去遍历原型链。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程