返回

JS启示录之原型

前端

在初学JavaScript的时候,我总是被“原型(链)”这个概念弄得晕头转向,面试题经常出现,网上也有很多关于它的文章。说实话,对于原型的理解固然很重要,但它算不上最难,甚至称不上“难点”,仅仅是一个必须懂的东西而已,不信?听我一一道来。

原型是什么?

原型是JavaScript中一个非常重要的概念,它是对象的一个特殊属性,指向创建该对象的构造函数。在JavaScript中,所有的对象都是通过构造函数创建的,而构造函数本身也是一个对象,所以构造函数也有原型。

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

const person = new Person('John Doe', 30);
console.log(person.constructor); // Person
console.log(person.constructor.prototype); // Person {}

从上面的代码中可以看出,person对象的原型是Person构造函数的原型对象。我们可以通过person.constructor.prototype来访问它。

原型链是什么?

原型链是一个对象的原型对象的原型对象,依次类推。在JavaScript中,每个对象都有一个原型链,原型链的顶端是Object.prototype对象。

console.log(person.__proto__); // Person {}
console.log(Person.prototype); // Person {}
console.log(Object.prototype); // {}

从上面的代码中可以看出,person对象的原型链是Person.prototype -> Object.prototype

原型链有什么用?

原型链的主要作用是实现继承。在JavaScript中,子类可以通过继承父类的原型对象来获得父类的属性和方法。

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

Student.prototype = Object.create(Person.prototype);

const student = new Student('Jane Doe', 20, 'Computer Science');
console.log(student.name); // Jane Doe
console.log(student.age); // 20
console.log(student.major); // Computer Science

从上面的代码中可以看出,Student类继承了Person类的原型对象,因此Student类的实例可以访问Person类的属性和方法。

toString()方法

toString()方法是JavaScript中一个内置的方法,它可以将一个对象转换为字符串。toString()方法的默认行为是调用对象的[[Get]]内部方法,该方法会沿着原型链向上查找,直到找到一个具有该属性的原型对象。如果找到,则返回该属性的值;否则,返回undefined

const person = new Person('John Doe', 30);
console.log(person.toString()); // "[object Person]"

const student = new Student('Jane Doe', 20, 'Computer Science');
console.log(student.toString()); // "[object Student]"

从上面的代码中可以看出,person对象的toString()方法返回了"[object Person]",而student对象的toString()方法返回了"[object Student]"。这是因为person对象的原型链中第一个具有toString()属性的原型对象是Person.prototype,而student对象的原型链中第一个具有toString()属性的原型对象是Student.prototype

利用toString()实现继承

我们可以利用toString()方法来实现继承。我们可以将父类的toString()方法复制到子类的原型对象中,这样子类的实例就可以访问父类的toString()方法。

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

Student.prototype = Object.create(Person.prototype);
Student.prototype.toString = Person.prototype.toString;

const student = new Student('Jane Doe', 20, 'Computer Science');
console.log(student.toString()); // "[object Person]"

从上面的代码中可以看出,student对象的toString()方法返回了"[object Person]"。这是因为我们复制了Person.prototypetoString()方法到Student.prototype中。

结语

原型(链)是JavaScript中一个非常重要的概念,它对于理解继承非常重要。通过原型链,我们可以实现子类继承父类的属性和方法。toString()方法可以用来更方便的从原型链继承属性和方法。