构造函数创建对象

function Person() {}
var person = new Person()
person.name = 'Dragon'
console.log(person.name) // Dragon

Person 就是一个构造函数,使用new实例化一个对象person

prototype

每个函数都有一个prototype属性

function Person() {}

Person.prototype.name = 'Dragon'
var person1 = new Person()
var person2 = new Person()
console.log(person1.name)  // 'Dragon'
console.log(person2.name)  // 'Dragon'

从上面可以发现person1和person2打印出的值都是 'Dragon', 到底函数prototype属性指向的是什么?

每一个JavaScript对象(null除外)在创建的时候就会关联另外一个对象,这个对象就是原型,每一个对象都会从原型继承属性。所以函数的prototype属性指向了一个对象,这个对象就是调用该构造函数实例化的原型,也就是person1和person2的原型。

proto

每一个JavaScript对象(除了null)都具有一个属性,叫proto,这个属性会指向该对象的原型。

function Person() {}
var person = new Person()
console.log(person.__proto__ === Person.prototype) // true

如果实例对象和构造函数都可以指向原型,那么是否有属性可以指向构造函数或者实例?

constructor

因为一个构造函数可以生成多个实例,所以指向实例是没有的。但是原型指向构造函数是有的,每个原型都有一个constructor属性指向关联的构造函数

function Person() {}
console.log(Person === Person.prototype.constructor) // true

所以:

function Person() {}
var person = new Person()

console.log(person.__proto__ === Person.prototype) // ture

console.log(Person.prototype.constructor === Person) // true

console.log(Object.getPrototypeof(person) === Person.prototype) // true

实例和原型

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还找不到,就找原型中当原型,直到找到位置。

function Person() {}

Person.prototype.name = 'dragon'

var person = new Person()
person.name = 'dragon2'
console.log(person.name) // dragon2

delete person.name
console.log(person.name) // dragon

在这里,我们给person添加name属性,当打印person.name的时候,就会出现 dragon2

当删了perosn的name的时候,读取person.name在person对象中就找不到name的属性,那么person的原型就是person.proto,也就是Person.prototype中查找,索性是找到了。。。

如果没找到,那就要继续找,直到找到原型的原型啦~

原型的原型

var obj = new Object()
obj.name = 'dragon'
console.log(obj.name) // dragon

所以原型对象就是通过Object构造函数生成的。

原型链

console.log(Object.prototype.__proto__ === null) // true

所以Object.prototype.proto的值为null和Object.prototype没有原型是一样的,所以找到Object.prototype就不用继续找了

补充

constructor

function Person() {}
var person = new Person()
console.log(person.constructor === Person) // true

当获取person.constructor时候,person里面是没有constructor的,就会从person.prototype中获取,所以:

Person.constructor === Person.prototype.constructor

proto

proto不存在Person.prototype中,因为他来自于Object.prototype,可以当作是一个getter/setter,当使用到obj.proto时,可以理解成返回了Object.getPrototypeOf(obj)

总结

此文仅简单了解原型与原型链,深入待续…


千万别成为大多数人