理解Javascript_05_原型继承原理javascript

对于面向对象的基础语法在此我就不重复了,对面向对象不熟悉的朋友可以参看《使用面向对象的技术创建高级 web 应用程序》一文。

prototype与[[prototype]]

在有面象对象基础的前提下,来看一段代码:

//animal构造函数

function animal(name){

this.name = name;

}

//animal原型对象

animal.prototype = {

id:"animal",

sleep:function(){

alert("sleep");

}

}

var dog = new animal("旺才");

alert(dog.name);//旺才

alert(dog.id);//animal

dog.sleep()//sleep

其对应的简易内存分配结构图:

现在让我们来解释一下这张内存图的来龙去脉:

首先明确一点[[prototype]]与prototype并不是同一个东西。

那先来看prototype,每一个函数对象都有一个显示的prototype属性,它代表了对象的原型,更明确的说是代表了由函数对象(构造函数)所创建出来的对象的原型。结合本例,animal.prototype就是dog的原型,dog所引用的那个对象将从animal.prototype所引用的对象那继承属性与方法。

每个对象都有一个名为[[prototype]]的内部属性,指向于它所对应的原型对象。在本例中dog的[[prototype]]指向animal.prototype,大家都知道,animal.prototype也是一个对象,即然是一个对象,那它必然也有[[prototype]]属性指向于它所对应的原型对象,由此便构成了一种链表的结构,这就是原型链的概念。额外要说的是:不同的js引擎实现者可以将内部[[prototype]]属性命名为任何名字,并且设置它的可见性,前且只在js引擎内部使用。虽然无法在js代码中访问到内部[[prototype]](firefox中可以,名字为__proto__因为mozilla将它公开了),但可以使用对象的 isprototypeof()方法进行测试,注意这个方法会在整个prototype链上进行判断。

注:关于函数对象的具体内容,将在后继的博文中讲解。

属性访问原则

使用obj.propname访问一个对象的属性时,按照下面的步骤进行处理(假设obj的内部[[prototype]]属性名为__proto__):

1. 如果obj存在propname属性,返回属性的值,否则

2. 如果obj.__proto__为null,返回undefined,否则

3. 返回obj.__proto__.propname

调用对象的方法跟访问属性搜索过程一样,因为方法的函数对象就是对象的一个属性值。

提示: 上面步骤中隐含了一个递归过程,步骤3中obj.__proto__是另外一个对象,同样将采用1, 2, 3这样的步骤来搜索propname属性。

这就是基于prototype的继承和共享。其中object1的方法fn2来自object2,概念上即object2重写了object3的方法fn2。

javascript对象应当都通过prototype链关联起来,最顶层是object,即对象都派生自object类型。

结合是上面的理论,让我们再来看一个更加复杂的示例,他明确的解释了prototype、[[prototype]]、原型链以及属性访问的相关要点:

//animal构造函数

function animal(name){

this.name = name;

}

//animal原型对象

animal.prototype = {

id:"animal",

sleep:function(){

alert("sleep");

}

}

function human(name,age){

animal.call(this,name);

this.age = age;

}

human.prototype = new animal();

human.prototype.id = "human";

human.prototype.say = function(){

alert("hello everyone,my name is "+this.name +",i'm "+this.age+" and i'm a "+this.id);

}

//human相关调用

var jxl = new human('笨蛋',25);

alert(jxl.name);//笨蛋

alert(jxl.id);//human

jxl.say();//hello everyone,my name is 笨蛋,i'm 25 and i'm a human

alert(animal.prototype.isprototypeof(jxl));//true

alert(object.prototype.isprototypeof(jxl));//true

根据上面的代码,你能画出相应的内存图吗?好,让我们来看一下:

注:prototype的根为object.prototype,对象object.prototype的内部[[prototype]]属性为null.

其实,这里还有很多东西可以讲,但在其原理都在这张图上了,可试着调整一下代码的次序,如将human.prototype.id = "human";放在human.prototype = new animal();的前面,看一下运行结果,解释一下为什么之类的,你可以学到很多。

我发现,通过内存来展现程序内部运行细节真的是太完美了!

参考:

http://www.cnblogs.com/riccc/archive/2008/02/15/javascript-object-model-execution-model.html


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值