认识原型
构造函数与实例对象
构造函数与普通函数并没有什么区别,只不过是通过new
关键字来创建实例对象,我们通常使用首字母大写来区分构造函数与普通函数。(不是说构造函数必须首字母大写,小写也不会有什么问题)
function Person(name, age) {
this.name = name
this.age = age
}
let p = new Person("花生", 18)
console.log(p); //Person {name: '花生', age: 18}
其中Person()被称为构造函数,p就是通过new生成的实例对象。
原型对象
每个函数类型的数据都有一个prototype
属性,该属性指向一个对象就是原型对象(显式原型属性)
该原型对象有一个constructor
属性,指向该构造函数
实例对象上有一个__proto__
属性指向原型对象(隐式原型属性)
原型链
既然原型对象也是对象,是不是也应该有一个__proto__
属性,指向对应构造函数的原型对象呢?
事实上就是Object()
当我们访问实例上的属性或者方法是,首先在自身寻找,找不到的话会按照隐式原型属性(__proto__
)继续找,直到找到Object.prototype
,如果还没找到,因为在继续找会找到null,所以会返回undefined
。
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.sex = "male"
let p = new Person("花生", 18)
console.log(p.sex); //male
console.log(p.sex1); //undefined
可以看出,整个查找过程都是顺着__proto__属性,一步一步往上查找,形成了像链条一样的结构,这个结构,就是原型链。所以,原型链也叫作隐式原型链。
在Vue2中有一条内置的属性,实现了vc可以访问到vm身上的所有属性,当我们在Vue上增加了某些属性或者方法xxx
后,可以直接在组件中this.xxx
访问到:
VueComponent.prototype.__proto__ = Vue.prototype
原型链和instanceof
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
上面的例子,我们继续
function Person(name, age) {
this.name = name
this.age = age
}
let p = new Person("花生", 18)
console.log(p instanceof Person); //true
console.log(p instanceof Object); //true
Function
函数是可以被执行的对象,函数是不是也有__proto__
?是的,所有的函数都是Function()
的实例。
上图
function Person(name, age) {
this.name = name
this.age = age
}
let p = new Person("花生", 18)
console.log(p instanceof Person); //true
console.log(p instanceof Object); //true
console.log(Person instanceof Object); //true
console.log(Person instanceof Function); //true
console.log(Object instanceof Function); //true
console.log(Function instanceof Function); //true
console.log(Function instanceof Object); //true
console.log(Object instanceof Object); //true
console.log(Object.prototype.__proto__ === Object.prototype); //false
总结
- 所有函数都是Function()的实例
- 所有原型对象都是Object()的实例
- 原型链的尽头是Object.prototype