Published on

理解Javascript的原型链

Authors

要理解原型链,首先要清楚理解以下几点:

  • 所有函数都是Function的实例化,都包含prototype属性,即原型对象。
  • 所有对象都有proto属性,该属性指向对象构造函数的prototype原型对象。
  • prototype原型对象的constructor属性指向它所在的原型对象的构造函数,即构造函数本身。
  • prototype是针对函数说的,proto是针对对象说的。
  • 函数本身也是对象。

认识到以上几点,我们先看一下原型链:

function setName() {
  this.name = 'mark'
}

function setAge() {
  this.age = 20
}

setAge.prototype = new setName()

var obj = new setAge()
console.log(obj.name, obj.age) //mark 20

console.log(obj.constructor === setName) //true

上面代码我们使用构造函数setAge()实例化一个对象obj,其中,age由构造函数写入,而name属性是有setAge的原型对象setName写入的。obj.constructor === setName 返回true是因为,在obj对象的构造函数中,并没有直接的consructor,它的constructor属性是通过proto属性继承的,而proto指向obj的构造函数的prototype对象,即setAge.prototype,也就是setName,所以会返回true。

那么,最简单的一条原型链就应该为,实例对象《== 构造函数 《== 构造函数原型对象 《== Object 《== Object.prototype 《== null,而原型对象中的构造函数(constructor属性)都等于它所在的构造函数。

function createO() {
  this.x = 1
}

var o = new createO()

console.log(o.__proto__) //createO.prototype
console.log(o.__proto__.__proto__) //Object
console.log(o.__proto__.__proto__.__proto__) //null

那么说白了,原型链的本质就是实例化对象和原型对象(prototype)之间形成的继承链条。

再说一下继承:

使用原型链最常用的继承方式:

function Person(name) {
  this.name = name
}
Person.prototype.showName = function () {
  console.log(this.name)
}
function Student(name, age) {
  Person.call(this, name)
  this.age = age
}
Student.prototype = new Person()
Student.prototype.contructor = Student
Student.prototype.showAge = function () {
  console.log(this.age)
}
var stu = new Student('张三', 12)
stu.showName()
stu.showAge()

参考文献: https://www.cnblogs.com/DF-fzh/p/5619319.html https://www.cnblogs.com/Yirannnnnn/p/4896542.html