js中原型链理解

本文固定连接:js中原型链理解_玖相逢的博客-CSDN博客

假设有这么一段代码:

    function fn (){
this . prop = {};
}
var o = new fn() ;
console . log( o . __proto__ === fn . prototype) ; //true
console . log( fn . prototype . __proto__ === Object . prototype) ; //true
console . log( Object . prototype . __proto__) ; //null

从输出的结果可以看出来,整条原型链为:
    1、o.__proto__ ---> fn.prototype, 
    2、fn.prototype.__proto__ ---> Object.prototype 
    3、Object.prototype.__proto__ ---null 原型链结束

如果存在继承关系,则子类的原型对象的__proto__属性(son.prototype.__proto__)会指向父类的原型对象(father.prototype),father.prototype.__proto__ 再继续指向父类的父类的原型对象,以此类推,最后指向Object.prototype
 

例如:

    //es5中才有的Object.create,这里先这样兼容一下吧(可以参考最下方的参考链接查看兼容的浏览器)
if ( typeof Object . create !== " function ") {
Object . create = function ( proto , propertiesObject ) {
if ( typeof proto !== ' object ' && typeof proto !== ' function ') {
throw new TypeError( ' Object prototype may only be an Object: ' + proto) ;
} else if ( proto === null) {
throw new Error( " This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument. ") ;
}
if ( typeof propertiesObject != ' undefined ') throw new Error( " This browser's implementation of Object.create is a shim and doesn't support a second argument. ") ;
function F () {}
F . prototype = proto ;
return new F() ;
};
}
 
function grandpa ( name ){
this . name = name ;
}
grandpa . prototype = {
getName : function (){
console . log( ' my name is ' + this . name) ;
}
}
function father ( name ){
grandpa . call( this , name) ;
}
father . prototype = Object . create( grandpa . prototype) ;
father . prototype . constructor = father ;
function son ( name ){
father . call( this , name) ; //这样写目的是让son的实例也拥有父类函数内部的属性与方法(非prototype);
};
son . prototype = Object . create( father . prototype) ;
son . prototype . constructor = son ; //这样的是将实例的construction指向son 即 实例.constructor 的值为 ‘function son(name){father.call(this,name);}’
var sonModel = new son( ' son ') ;
console . log( sonModel . name) ; //son
sonModel . getName() ; //my name is son

这段代码的意思是:son继承自father,father继承自grandpa(当然js可以实现多继承,但是针对多继承的情况,原型链在我认为来说是错误的,因为他只链了第一个继承的原型对象(用jquery的写法的话,也有可能连到其他父对象,但是只能链一个))

原型链在属性搜索中的作用:

    寻找一个属性会遍历整条原型链

    Object . prototype . d = 4 ;
function fn (){
this . a = 1 ;
}
fn . prototype . b = 2 ;
fn . prototype . c = 3 ;
function fn2 (){
fn . call( this) ;
this . c = ' fn2中的c ' ;
}
fn2 . prototype = Object . create( fn . prototype) ;
var fn2Model = new fn2() ;
console . log( fn2Model . c) ; //fn2中的c
console . log( fn2Model . d) ; //4

    上面这段代码,fn2Model对象本身只有a c两个属性(直接被注册到this上了),同时,在fn.prototype中b c两个属性被继承,但最后fn2Model.c的值为‘fn2中的c’,fn2Model.d的值为4,可以得出结论

    属性的搜索机制:先搜索实例对象本身具有的属性(如果写法中在子类内部不写 父类.call(this) ,那么可以理解为是方法内部的属性),找到则返回,找不到则会找原型,一次顺着原型链依次向上查找,直到原型链结束。

    包括枚举一个实例对象时候,也会通过原型链查找到原型链结束 即Object.prototype.__proto__

    Object . prototype . d = 4 ;
function fn (){
this . a = 1 ;
this . b = 2 ;
}
fn . prototype . c = 3 ;
fn . prototype . getName = function (){
console . log( this . a + this . b + this . c + this . d) ;
};
var o = new fn() ;
for( var item in o) {
console . log( item) ; //打印结果 a b c getName d
}
o . getName() ; //10

从输出的结果来看,枚举的属性还包括了d,而fn函数本身是没有这个属性的,且fn.prototype.__proto__最终是指向Object.prototype,所以最终枚举的属性包含了d。
本文固定连接:js中原型链理解_玖相逢的博客-CSDN博客
参考链接:
    继承与原型链 - JavaScript | MDN
    Object.create() - JavaScript | MDN

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值