JavaScript

JavaScript原型链

Posted on 2019-01-02,3 min read

原型链是整个JavaScript面向对象的基础,也可以理解为是基石,是非常重要的一部分。如果没有掌握原型链就不能说明自己熟悉JavaScript。这篇文章就整理一下关于原型链的知识。

说到原型,首先想到的就是在定义构造函数的方法时,直接定义在构造函数的prototype上。这样的好处是,通过该构造函数生成的实例所拥有的方法都是指向一个函数的索引,这样可以节省内存。

1. 构造函数、实例、原型三者之间的关系

三角形关系

任何函数都有一个prototype属性,该属性是一个对象

console.log(typeof Student.prototype); // object

构造函数的prototype对象默认都有一个constructor属性,该属性指向prototype对象所在的函数。

console.log(Student.prototype.constructor === Student); // true

实例对象内部会包含一个指向构造函数的 prototype 对象的指针 __proto__

console.log(s1.__proto__ === Student.prototype); // true

实例对象可以直接访问原型对象的成员变量。

// 给原型对象上定义一个方法
Student.prototype.sayHi = function(){
  console.log('Hi!');
};
// 实例对象可以直接访问
s1.sayHi(); // Hi!

2. 原型链

简单理解就是原型组成的链,对象的__proto__它的是原型,而原型也是一个对象,也有__proto__属性,原型的__proto__又是原型的原型,就这样可以一直通过__proto__想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。

原型链

补充:

  • 只有函数有prototype,对象是没有的。
  • 函数也是有__proto__属性的,因为函数也是对象。函数的__proto__指向的是Function.prototype

也就是说普通函数是Function这个构造函数的实例。

console.log(Student.__proto__ === Function.prototype); // true

3. instanceof的原理

上一篇文章数据类型转换提到了instanceof,是用来判断数据的类型的,返回的是布尔值。

它的原理就是判断实例对象的__proto__和生成该实例的构造函数的prototype是不是引用的同一个地址。是就返回true,否就返回false

注意:实例的instanceof在比较的时候,与原型链上向上找的的构造函数相比都是true。

console.log(s1 instanceof(Student)); // true
console.log(s1 instanceof(Object)); // true

那怎么判断实例是由哪个构造函数生成的呢?这时候就要用到constructor了。

console.log(s1.__proto__.constructor === Student); // true
console.log(s1.__proto__.constructor === Object); // false

下一篇: JavaScript数据类型和类型转换