原型&&原型链

261 阅读3分钟

这一切都要从构造函数开始说起……

构造函数

function Student(){

}
    
let student = new Student()

函数Student为构造函数,student是构造函数Student的实例,也被称为实例对象。

constructor

function Student(){
    this.id = 1
    this.remark = function(){
        console.log('三好学生获得者')
    }
}
let student = new Student()
console.log(student.constructor)   // Student(){}
console.log(student.id);   // 1

实例都有一个构造函数属性constructor指向构造函数,通过构造函数创建的对象拥有构造函数内部定义的属性和方法。

解读:实例student的constructor属性指向构造函数Student;实例student的id属性继承了构造函数的id属性,方法同理。

function Student(){

}
    
let student1 = new Student()
let student2 = new Student()
console.log(student1.constructor===Student)     // true
console.log(student2.constructor===Student)     // true
console.log(student1.constructor===student2.constructor)    // true

由上可知:同一个构造函数的不同实例的constructor指向这个构造函数.

原型 prototype

function Student(){

}
Student.prototype.id = 1
    
let student1 = new Student()
let student2 = new Student()
console.log(student1.id)    // 1
console.log(student2.id)    // 1

在JS中,每一个函数对象(函数也是对象)都有一个特殊的属性叫做原型(prototype),指向另一个对象,这个对象被称为原型对象,原型对象是用来共享属性和方法。

解读:上边代码中的实例对象student的prototype属性指向构造函数Student.prototype,Student.prototype被称为原型对象,继承原理所以student1和student2可以读取id属性的值。

原型对象 Student.prototype

image.png

Student.prototype.constructor === Student 
// true
  • 原型对象都有一个constructor指向构造函数本身
  • 原型对象是一个普通对象,包含属性和方法
  • 原型对象的属性和方法会被继承到所有通过原型链与他相连的对象
function Student(){
    this.name = 'xiaoming'
    this.say = function(){

    }
}
Student.prototype.sex = "man"
Student.prototype.Doing = function(){

}
const student1 = new Student()
const student2 = new Student()
console.log(student1.sex === student2.sex);   // true
console.log(student1.Doing === student2.Doing);   // true
console.log(student1.name === student2.name);   // true
console.log(student1.say === student2.say);   // false

解读: Doing为true是因为挂在原型上是同一个方法,堆区位置相同。say为false是因为student1和student2是两个独立的函数,say方法是互相独立堆区位置不同。

隐式原型__proto__

  • 在JS中,每个对象都有一个__proto__属性,这个__proto__被称为隐式原型
  • 指向创建它的构造函数的原型对象
  • __proto__存在的意义在于为原型链查找提供方向,原型链查找靠的是__proto__不是prototype
function Student(){

}
let student = new Student();
console.log(student.__proto__===Student.prototype);   // true

image.png

原型链

Student.prototype.__proto__ === Object.prototype   // true
Object.prototype.__proto__ === null   // true

原型对象的隐式原型__proto__ 就是Object.prototype。

所有的对象,包括构造函数的原型对象,最终都继承自 Object.prototype,这是js原型链的顶点

Object.prototype是原型链的顶端,不再有自己的原型,所以Object.prototype.__proto__指向null。

image.png

每个对象都有一个原型(prototype),它指向另外一个对象,而指向的对象又存在属性(__proto__)指向另外一个对象。当我们访问student的属性时,会先在对象定义的属性中进行查找,没找到就会沿着__proto__一路向上查找,最终形成一个链式结构,这个链式结构叫做原型链

总结

  • 在JS中,每一个对象(函数也是对象)都有一个特殊的属性叫做原型(prototype),它指向另一个对象,这个对象被称为原型对象,原型对象用来共享属性和方法。
  • 对象有一个属性__proto__指向构造函数原型对象,构造函数的原型对象也存在__proto__
  • 原型链的顶端是Object.prototype
  • 原型链的终点是null