这一切都要从构造函数开始说起……
构造函数
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
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
原型链
Student.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null // true
原型对象的隐式原型__proto__ 就是Object.prototype。
所有的对象,包括构造函数的原型对象,最终都继承自 Object.prototype,这是js原型链的顶点。
Object.prototype是原型链的顶端,不再有自己的原型,所以Object.prototype.__proto__指向null。
每个对象都有一个原型(prototype),它指向另外一个对象,而指向的对象又存在属性(__proto__)指向另外一个对象。当我们访问student的属性时,会先在对象定义的属性中进行查找,没找到就会沿着__proto__一路向上查找,最终形成一个链式结构,这个链式结构叫做原型链。
总结
- 在JS中,每一个对象(函数也是对象)都有一个特殊的属性叫做原型(prototype),它指向另一个对象,这个对象被称为原型对象,原型对象用来共享属性和方法。
- 对象有一个属性
__proto__指向构造函数原型对象,构造函数的原型对象也存在__proto__ - 原型链的顶端是Object.prototype
- 原型链的终点是null