一、原型链
function fn() {
}
var f = new fn()
console.log(f instanceof fn) //true
console.log(f instanceof Object) //true
console.log(fn instanceof Function) //true
console.log(fn instanceof Object) //true
instanceof 第一个参数A为对象,第二个参数B一般为函数
进行判定时沿着A的__proto__属性向后找,沿着B的prototype向前找,如果二者重合则判定为true
console.log(Object instanceof Object) //true
console.log(Function instanceof Object) //true
console.log(Object instanceof Function) //true
console.log(Function instanceof Function) //true
再来看几个复杂的,这是为什么呢。。看一下图
简单来说,他们之间构成了环。
这种通过原型关联起来的机制就是原型链
二、继承
js通过原型链实现了所谓的“继承”,这个继承和C++、java中的继承不同
看个例子
function fn() {
}
var f = new fn()
f.a = 10
fn.prototype.b = 20
var itme
for(itme in f){
console.log(itme) //a
}
此时在f中既有a又有b
但是创建一个新的对象g
var g = new fn()
for(itme in g){
console.log(itme) //b
}
就只有b这个属性了
所里f中的b和g中的b都是函数中的属性,而a则是f中自己定义的属性
也就是说
f.__proto__ 中含有a
fn.prototype中含有b
g.__proto__中什么都没有
当访问对象的某个属性时,先去他的 __proto__ 中找,如果找不到就沿着__proto__ 走,找定义他的函数的prototype,因为__proto__是指向“基类”的prototype的嘛,这样就通过原型链实现了“继承”。
等等…还有一个优先级的问题,比如a在f中定义了在fn中也定义了,不管定义顺序如何,都是先找f中的。
三、灵活的原型
如果我们吧function比作class,把对象比作class创建的实例,那么js中的对象要比其他强类型语言灵活多了。
当一个对象被new出来以后,可以动态地向里面加入各种属性,实在不行还可以动态地向function中加属性