JS原型与原型链详解

136 阅读2分钟

普通对象与函数对象

众所周知世间万物都可看作对象,但对象亦有区别,分为普通对象和函数对象。Object与Function是JS自带的函数对象,下面举例说明。

function f1(){}
let f2 = function(){}
let f3 = new Function()
let o1 = {}
let o2 = new Object()
let o3 = new f1()
let o4 = new new Function()
console.log(typeof f1) //function
console.log(typeof f2) //function
console.log(typeof f3) //function
console.log(typeof o1) //object
console.log(typeof o2) //object
console.log(typeof o3) //object
console.log(typeof o4) //object

通过上面的例子可以得出结论: 所有Function的实例都是函数对象,其他的都是普通对象,也包括Function的实例的实例。

构造函数

先来回顾下构造函数的知识

function Person(name,age,job){
    this.name = name
    this.age = age
    this.job = job
    this.sayName = function(){
        console.log(this.name)
}
}
let person1 = new Person('章三',18,"前端开发")
let person2 = new Person(“李四”,19,“后端开发”)
person1.sayName() //章三

person1和person2都是Person构造函数的实例,这两个实例内部都有一个constructor属性,它指向Person,即:

person1.constructor === Person
person2.constructor === Person

由此我们得出结论:实例对象内部的constructor属性是指向构造函数的

原型对象

在JS中,创建对象(函数也是对象)的时候都会在该对象内部预置一些属性,其中每个函数对象都会包含prototype属性,该属性指向该对象的原型对象。

function Person(){
    Person.prototype.name = "章三"
    Person.prototype.age = 18
    Person.prototype.job = "前端开发"
    Person.prototype.sayName = ()=>{console.log(this.name)}
}
let person1 = new Person()
person1.sayName()
let person2 = new Person()
person2.sayName()

结论:每个对象都有__prototype__属性,只有函数对象有prototype属性。 那什么是原型对象呢? 将上面的例子改下:

Person.prototype = {
    name:'章三',
    age:18,
    job:'前端开发',
    sayName:()=>{console.log(this.name)}
}

结论:原型对象就是一个普通对象,在默认情况下所有的原型对象都有一个constructor属性,它指向prototype所在的函数,即:

Person.prototype.constructor === Person

prototype

JS中在创建对象(无论是普通对象还是函数对象)时,对象内部都会预设__proto__属性,用来指向该对象的原型对象,即:

Person.__proto__ ===Person.prototype

请看下图

1430985-b650bc438f236877.webp 结论:

Person.prototype.constructor === Person
person1.__proto__ === Person.Prototype
person1.constructor === Person