js原型链图解
http://www.jb51.net/article/30750.htm
此文源于这篇文章,读了之后感觉原文有点乱,所以整理了一下,画了一张图,初学js不知道对原型链的理解对不对,还请各位大神指教。
下面图中被一条红线连起来的那3个对象,就是一条原型链。我的理解是:原型链就是由_proto_指针连起来的几个对象组成的一条对象链,使链下游的对象能继承链上游对象(**.prototype)的方法和属性。
直接看代码吧
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
//原型链 用于实现js的继承特性
Object.prototype.oShowMe = function (){document.write("function of the root obj<br>");};
Function.prototype.fShowMe = function(){document.write("function of the Function obj<br>");};
function MyFunc(){
var name = 'tom';
}
MyFunc.prototype.mShowMe = function(){document.write("user-defined function<br>");};
var mfObj = new MyFunc();
mfObj.mShowMe();//output: user-defined function
mfObj.oShowMe();//output: function of the root obj
//mfObj.fShowMe();//output:对象不支持“fShowMe”属性或方法
MyFunc.fShowMe();//output: function of the Function obj
MyFunc.oShowMe();//output: function of the root obj
//对new出来的对象的继承是无效的
//var OmfObj = new mfObj;
//OmfObj.oShowMe();//output: 对象不支持此操作
</script>
</head>
<body>
</body>
</html>
这段代码可以直接复制到一个jsp文件运行,读者可以先看下运行结果,自己对照图片思考下。这里我想用自己不科学的语言给你点提示:
1. 每个对象都有两个隐含属性:prototype和_proto_,以实现继承。
2. prototype也是个指针,指向自身的prototype即<this.prototype>,用于被子类继承。
3. _proto_可以理解为一个指针,指向父类的 <父类.prototype>,用于继承父类在prototype中声明的属性。
ps:上述几条为了方便理解,说的很不全面。也不标准,也为js里没有父类这种说法。
在上面这段代码中,我给Object,Function这两个js内部对象增加了oShowMe(),fShowMe()这两个方法,以查看Object和Function的子类有没有继承到这两个对象(的prototype)。
从其运行结果可以知道:
1. Object对象是所有对象的根类 ,所有的对象都继承自Object,所以图中几个<**.prototype>最后都指向<Object.prototype>,同时所有对象都能使用oShowMe()这个方法。
2. function MyFunc是个对象,继承自Object类 ,废话,第一条里面不说了么Object是所有对象的根,root
function aFunc(a,b){ return a+b; }
这是最常见的一种声明js函数的方法,同时这个函数又是一个js对象,最初我对这种方法非常不理解,干嘛要搞的这么含糊,想java那样定义明确的class,对象必须要new的多好,但这种规则,正是js比java灵活的体现,如果java是郭靖,那js一定是黄老邪,实在是太邪了。。。
跑题了,下面看另一种声明js函数的方法
Function aFunc = new Function(a,b,"return a+b");
这个函数是以对象的形式声明的,用Function声明对象的效果与用function声明函数是一样的,而且function这种声明方式(其实这样的声明的function被称为<aFunc.prototype>的constructor,即构造器,看图)在js解释器中的处理,也是先转换为Function对象声明的方式的。
所以如第一段代码所示:函数MyFunc可以调用到Object中的函数oShowMe();,因为MyFunc这个函数(也是对象)继承自Object。
3. 原型链的作用是实现继承:
如图中红线所示:我们调用mfObj.mShowMe();时,mfObj对象并未声明方法mShowMe,所以它沿着原型链向上层查找,在<MyFunc.prototype>中找到了mShowMe()。调用mfObj.oShowMe();时,mfObj同样沿着原型链向上层查找到<Object.prototype>才找到oShowMe();
这就实现了js方法中的继承,同时验证了提示中的第二,第三条。
我翻了下书总结下js实现继承的其他方法
1. 对象冒充
2. call()方法
3. apply()方法
4. 原型链
5.原型链+对象冒充 混合式
这些方法我还没看,看了之后有新的感悟的话,还会回来更新。
可能有些地方说的不太清楚,说的清楚的估计也难免有错误,希望大神不吝指正,大家共同学习。