返回

JavaScript入门:深入理解原型和原型链

前端

在JavaScript语言中,没有像Java那样的类,但它同样可以通过原型和原型链来实现继承、多态等面向对象编程的特性。然而,JavaScript的继承与Java的继承存在着本质区别。本文将从JavaScript的原型和原型链入手,带领你深入理解JavaScript独特的继承机制,并通过示例代码演示如何利用原型和原型链创建和使用对象。

1. JavaScript中的原型

每个JavaScript对象都有一个内部属性[[Prototype]],指向创建它的函数的prototype属性,称为对象的原型。原型是一个对象,它包含一组属性和方法,这些属性和方法可以被对象继承。

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

const person1 = new Person('John', 25);
console.log(person1.name); // 'John'
console.log(person1.age); // 25

在上面的示例中,Person函数的原型是一个对象,它包含一个name属性和一个age属性。当我们创建person1对象时,它会继承Person函数原型的nameage属性。

2. JavaScript中的原型链

原型链是指从一个对象一直到原型链顶端null的对象所形成的链条。每个对象都有一个原型,而原型的原型又指向它的原型,如此一直到原型链顶端。

const person1 = new Person('John', 25);
console.log(person1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null

在上面的示例中,person1对象的原型是Person函数的原型,Person函数原型的原型是Object对象的原型,Object对象的原型是null。因此,person1对象的原型链是person1对象、Person函数原型、Object对象原型和null

3. JavaScript中的继承

在JavaScript中,继承是通过原型链实现的。当一个对象被创建时,它会继承其原型对象的所有属性和方法。例如,在上面的示例中,person1对象继承了Person函数原型的nameage属性,以及Person函数原型中的其他属性和方法。

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

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

const person1 = new Person('John', 25);
person1.greet(); // 'Hello, my name is John and I am 25 years old.'

在上面的示例中,我们为Person函数的原型添加了一个greet方法,该方法用于向他人打招呼。当我们调用person1对象的greet方法时,它会继承自Person函数原型的greet方法,并使用person1对象自己的nameage属性来向他人打招呼。

4. JavaScript中的多态

在JavaScript中,多态也是通过原型链实现的。当一个对象调用一个方法时,JavaScript会沿着原型链向上查找该方法,直到找到第一个定义了该方法的对象。然后,JavaScript会调用该对象的方法。例如,在下面的示例中,person1对象调用了greet方法,JavaScript会沿着原型链向上查找该方法,直到找到Person函数原型中的greet方法,然后调用该方法来向他人打招呼。

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

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

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

Student.prototype = new Person();

Student.prototype.study = function() {
  console.log(`I am studying ${this.major}.`);
};

const student1 = new Student('Jane', 20, 'Computer Science');
student1.greet(); // 'Hello, my name is Jane and I am 20 years old.'
student1.study(); // 'I am studying Computer Science.'

在上面的示例中,Student函数继承自Person函数,并添加了一个study方法。当student1对象调用greet方法时,JavaScript会沿着原型链向上查找该方法,直到找到Person函数原型中的greet方法,然后调用该方法来向他人打招呼。当student1对象调用study方法时,JavaScript会沿着原型链向上查找该方法,直到找到Student函数原型中的study方法,然后调用该方法来学习。

总结

JavaScript中的原型和原型链是实现继承、多态等面向对象编程特性的关键。通过理解原型和原型链,你可以更深入地理解JavaScript的运行机制,并编写出更加健壮、可维护的JavaScript代码。