原型与原型链
prototype:每一个函数都有一个prototype属性,它默认指向一个object空对象, 即原型对象。
constructor:是prototype这个原型对象的属性,它指向该函数对象
原型对象不推荐直接使用,是给创建的实例对象访问的。
显式原型和隐式原型
prototype为显式原型属性,定义的时候添加
_proto_为隐式原型属性,创建对象的时候添加
有什么关系?
对象的隐式原型的值为对应的构造函数的显式原型的值
function Fn(){ //创建函数的时候,内部执行了this.prototype = {}
}
var fn = new Fn()
//在这条语句中,内部执行了this.__proto__ = Fn.prototype
console.log("对象隐式原型的值为",fn.__proto__)
console.log("该对象构造函数的显式原型的值为",Fn.prototype)
程序可以直接操作显式原型,但不能直接操作隐式原型
原型链
本质上是隐式原型链,作用是查找对象的属性(方法)
function Fn(){
this.test1 = function (){
console.log('test1')
}
}
Fn.prototype.test2 = function () {
console.log("test2")
}
var fn = new Fn()
fn.test1()
fn.test2()
当我们要找test1()函数的时候,先去Fn的实例对象里找,于是就找到了
当我们要找test2()函数的时候,先去Fn的实例对象里找,找不到就去proto所指向的对象里找,于是找到了
当我们要找toString()函数的时候,先去Fn的实例对象里找,找不到就去proto所指向的对象里找,找不到就去proto所指向的对象里找,于是找到了
- 函数的显示原型指向的对象默认是空Object实例对象(但Object本身)
- 所有的函数都是Function的实例,包括它本身。
- Object的原型对象是原型链的尽头
原型链的属性问题
原型链是用来查找属性的
当我们读取对象的属性值时,会自动到原型链中查找
当我们设置对象属性值时,不会查找原型链,如果当前对象中没有该属性,直接添加此属性并设置值。
function Person(){
}
Person.prototype.a="111"//设置显示原型中的属性a
var fn1 = new Person()
console.log(fn1.a)//实例对象开始在原型链上查找属性
var fn2 = new Person()
fn2.a = '123'//设置对象属性值,当前没有,则自动添加
instanceof
判断左边的对象是否为右边的实例
function Person(){
}
var fn1 = new Person()
console.log(fn1 instanceof Person)//输出为true
console.log(fn1 instanceof Object)//输出为true
判断逻辑
A instanceof B
如果B函数的显式原型对象在A对象的原型链上,那么则为true
fn1 instanceof Person
fn1的隐式原型指向Person的显式原型
测试题
(1)
var A = function(){
}
A.prototype.n = 1
var b = new A()
A.prototype = {
n:2,
m:3
}
var c = new A()
console.log(b.n, b.m, c.n, c.m)//1 undefined 2 3
(2)
var F = function(){}
Object.prototype.a = function(){
console.log("a()")
}
Function.prototype.b = function(){
console.log("b()")
}
var f = new F()
f.a()
f.b()
F.a()
F.b()