在学习 JavaScript 中的继承机制时,我们常常会遇到原型和原型链这两个概念。在初学阶段,不理解这些概念很容易陷入迷茫,甚至会导致学习 JS 的路程变得曲折。本文将介绍 JavaScript 原型和原型链的概念、设计思想以及相关的使用方法。
什么是原型?
JavaScript 是一门基于对象的语言,每个对象都有一个原型(prototype),原型是一个对象或 null 值,它定义了该对象所具有的属性和方法。当读取一个对象的属性或执行一个对象的方法时,如果当前对象本身没有这个属性或方法,那么 JavaScript 就会从该对象的原型中查找这个属性或方法,并递归查找到其原型链上的所有对象,直到找到该属性或方法为止。
在 JavaScript 中,每个函数对象都有一个 prototype 属性,该属性指向该函数的原型对象。当使用 new 操作符创建一个对象时,该对象的原型就被设置为构造函数的 prototype 属性的值。例如:
function Person(name) {
this.name = name;
}
var person1 = new Person("李三");
// person1 的原型是 Person.prototype
console.log(person1.__proto__ === Person.prototype); // 输出:true
什么是原型链?
JavaScript 的对象之间不是完全独立的关系,它们之间是通过原型链(prototype chain)相互关联的。原型链指的是对象之间的一种继承关系,每个对象都有一个原型对象,而原型对象也可能有自己的原型,这样一直递归下去,就形成了原型链。
当读取一个对象的属性或执行一个对象的方法时,如果该对象本身没有这个属性或方法,JavaScript 就会沿着该对象的原型链向上查找,直到找到该属性或方法为止。如果到达了原型链的顶端还没有找到该属性或方法,则返回 undefined。
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
function Student(name, grade) {
Person.call(this, name);
this.grade = grade;
}
// 继承了 Person 的属性和方法
Student.prototype = Object.create(Person.prototype);
// 在 Student.prototype 上添加自己的属性和方法
Student.prototype.study = function() {
console.log(`${this.name} is studying in grade ${this.grade}`);
};
var student1 = new Student("李三", 3);
student1.sayHello(); // 输出:Hello, my name is 李三
student1.study(); // 输出:李三 is studying in grade 3
在上面的例子中,我们定义了两个构造函数 Person 和 Student,并通过 Student.prototype = Object.create(Person.prototype); 实现了 Student 对象继承自 Person 对象的属性和方法。当我们调用 student1.sayHello() 方法时,JavaScript 沿着该对象的原型链向上查找,找到了 Person.prototype 中的 sayHello() 方法。当我们调用 student1.study() 方法时,则直接在 Student.prototype 中查找到了该方法。
总结
通过本文的介绍,我们可以明确 JavaScript 中原型和原型链的概念以及使用方法。理解原型和原型链的设计思想,可以帮助我们更好地理解 JavaScript 的对象模型,从而更好地编写高质量的代码