复制代码 代码如下:
//方法一
//Prototype框架采用了此种方法
Hoozit.prototype = new Gizmo(2);
Hoozit.prototype.constructor = Hoozit;
//方法二
function Hoozit(id) {
this.id = id;
this.constructor=Hoozit;
}
//具体两种方法有什么区别,请参考《JAVASCRIPT语言精髓与编程实践》158~159页。
有兴趣的可以结合上面的图,想想这两种方法的Hoozit.prototype.constructor应该放在图的什么位置?想不明白的可以和我在交流。
下面看一下《JAVASCRIPT语言精髓和编程实践》书上的一张图(156~157页):

个人认为这张图下面的那个constructor属性的指向是不是有问题?书上面表达的意思肯定没有问题,但这张图画的很困惑。和我上面的解释不太一样?先不说这个了,大家自己研究研究吧。
下面我们再来说一下我给出的原型继承图中的右边灰色的箭头部分。从这部分能够看出继承的关系。所有未经过变动的函数(构造器)的原型,他们都会继承自Object对象。
alert(Gizmo.prototype instanceof Object.prototype.constructor); //true
这样原型的继承关系就连接起来了。其实说白了,就是一个函数的prototype链向另一个函数实例,然后不断的这样进行下去,最上面的函数链接Object至对象实例,OK,所有函数就都连接起来了。
PS:
“还有要注意的是只有在new Gizmo()之后,才能添加test等其它方法,这个顺序不能倒过来!“ 这个问题是不是清楚了呢?
下面看几个例子,说明几个问题:
复制代码 代码如下:
function Gizmo(id) {
this.id = id;
this.ask=function(){
alert("gizmo--ask:"+this.id);
}
function privateMethod(){
return "gizmo--privateMethod";
}
privateMethod2=function(){
return "gizmo--privateMethod2";
}
}
Gizmo.prototype.toString = function () {
return "gizmo--toString:" + this.id;
};
Gizmo.prototype.id="gizmo3";
function Hoozit(id) {
this.id = id;
}
Hoozit.prototype = new Gizmo("gizmo1");
var g=new Gizmo("gizmo2");
var h=new Hoozit("hoozit");
问题一:
复制代码 代码如下:
h.ask=function(){
alert("h.ask");
}
h.ask();
delete h.ask; //"h.ask"
h.ask(); //"gizmo--ask:hoozit"
delete h.id
h.ask(); //"gizmo--ask:gizmo1"
delete Hoozit.prototype.id
h.ask(); //"gizmo--ask:gizmo3"
/*
这里要说明的问题是:对象是如何找到属性和方法的?
第一步:先在实例对象上找ask方法,找到了,调用。第一个ask说明了这个问题
第二步:如果实例上没有ask方法,在自己的原型对象里面找ask方法,找到调用(没有给出这样的示例)
第三步:如果自己的原型中没有,回溯原型链,在父原型链中找ask方法,找到调用,第二个ask说明了这个问题,这里会一直递归找到Object对象,如果还没找到,那就会报错了
*/
/*
再来看属性查找:
首先找实例对象上的属性,所以第二个ask输出"gizmo--ask:hoozit",即id="hoozit"
然后找自己原型中的属性,删除掉h.id之后,找到原型上的属性,所以id="gizmo1"
接着递归原型链,找父对象原型中的属性,一直找到Object对象,所以删除掉Hoozit.prototype.id之后,id="gizmo3"
*/
问题二:
复制代码 代码如下:
Gizmo.prototype.question = function () {
alert("gizmo--question:" + this.id);
};
h.question();
/*
方法可以随时添加,添加完之后就可以调用
*/
问题三:
复制代码 代码如下:
Hoozit.prototype.toString = function () {
return "hoozit--toString:" + this.id;
};
alert(h);
delete Hoozit.prototype.toString;
alert(h);
/*
这个问题和问题一有些重复,这里更清楚的看出,删除掉自己原型上的方法之后,就会找父原型中的方法
*/
问题四:
复制代码 代码如下:
h.question.call(g);
alert(h.toString.call(g));
h.question.apply(g);
alert(h.toString.apply(g));
/*
可以利用apply和call方法把要调用的方法绑定到其它实例。通过结果可以看出上面那种方法调用输出的id是g对象的,而不是h对象的
*/
问题五:
复制代码 代码如下:
alert(h.privateMethod());
alert(g.privateMethod2());
/*
上面的任意一个调用都会报错,也就是说通过显示命名函数或者匿名函数但是不加this的声明方式定义在函数之内的函数,是不能被外界访问的。这里一定注意第二种private方法声明,省略了this外面就访问不到了!
*/
/*
命名函数:(函数名字为func1)
function func1(){}
匿名函数:(注意这里,func1不是函数的名字,仅仅是个别名而已,可以通过func()来调用这个匿名函数)
func1=function(){}
*/
pdf文件下载http://xiazai.jb51.net/200907/books/javascript_yuanxing.rar