javascript中的模式解析——原型模式(重新认识)

前两天我写了一份javascript中的模式解析——原型模式,感谢@枫小炀   及时指出我的错误。在经过多次查阅书籍和许多大神的博客后,我对原型模式的认识加深了许多,所以我必须要再次发一篇文章,来纠正我上一篇文章的错误观点啊

首先做一些对于要用到的名称做一些注解:

function Foo () {}
var foo = new Foo();

 

我把 Foo称作foo的克隆类(也就是大家认为的父类,但我觉得父类误导性太大)  把foo称作Foo的实例 把Foo.prototype称作Foo的原型对象,同时也是foo的继承父类

我把[[prototype]]属性用到时写为  _proto_(一些浏览器这么规定的)

每一个对象存在[[prototype]]属性,这个属性决定他的原型链,指向它继承的对象

每个对象也都存在prototype属性,这个属性指向它的原型对象

再做一些必要的 定理:

  1. Function是最顶层的构造方法,所有对象都由Function方法构造,包括Object方法,Function方法(有些人把这个认为是Function方法的自生性,不用纠结,不管是什么原因,只要记住Function是方法也是对象就行)
  2. 所有的方法(就是克隆类)都继承Function.prototype对象(包括Function方法 通过定理1可得)
  3. 每个对象的_proto_属性(注意不是prototype属性)都指向自己的继承父类,也就是他的克隆类的原型对象,也就是Foo.prototype对象(object对象)
  4. 对象的原型链是基于_proto_属性的指向连接,也就是说,原型链是是根据_proto_属性来确定,而不是prototype属性(这是我思想转变的最大的不同,也是原来错误最大的一点)
  5. Object对象是最顶层的对象,所有对象都可以算作他的实例,当然也包括原型对象,也就是说所有对象的_proto_属性最终都会顺着原型链指向Object.prototype
  6. 所有的原型对象的_proto_最终都指向Object.prototype(通过定理3)
  7. Object.prototype的_proto_指向null(最顶级的原型对象,再往上真的没有了)
  8.  prototype属性指向自己的原型对象
  9. 不要纠结是先有Object对象,还是先有Function方法,就跟先有鸡还是现有蛋一样,相互依赖,同时诞生
  10. 确定一个对象A是不是B类,我们通过instanceof方法,这个方法的意思是检查 A的原型链上是否存在B.prototype,存在为true,不存在为false

 

这么多的定理,都是我得出的一些想法和理解,我不能向大家说这一定是对的,我只能说这是我理解中必须存在的,必须被证明的东西。我觉得我弄明白这些东西的时候,我已经思考原型模式一个星期左右了,思想观点几经转变,甚至是反向的转变,看过许多大牛的博客文章,查阅了 javascript高级程序设计(第四章,第六章), javascript语言精粹修订版(P22, P50,P58),高性能javascript(第二章P27),说了这么多,并不是要自夸我爱学,我只是想说一个事实,看谁的一篇文章或者博客,你确定你能瞬间理解吗?我觉得不太现实,你需要看完理解,再看,再理解,到有一天你觉得似乎都能理解了,大牛大神说的跟你想的一样了,那才可以,但是那也不一定是最后的结果,还需要今后不断的回想,确认,甚至重新理解。

好了,不管上面的定理你明白或者不明白,甚至你觉得是错的(这个请务必留言通知我),我要把我理解这些定理的过程给大家讲一下

 

 首先是实例与类的关系,我们常这样认为 function A (){}; var b= new A(),那么A是b的父类,但是这个父类会误导我们以为b是继承A的,其实不是,从生理的角度来说,如果克隆一个你出来,你是他父亲吗?不是,因为你们的基因是一样的,不存在父子关系,但是你们是兄弟吗?也不是,克隆的你是从你身上得到的基因。但是如果我如果要问克隆的你的基因从哪继承的,应该说是你父亲和母亲把,当然你肯定也是从你父母那里继承的基因。

 

所以我认为 new操作就相当于克隆, 那暂且同意我把A称作b的克隆对象 但是又有个问题,A是不是也有一个克隆对象啊,有,Function对象(参考定理1,2),那b的继承父类(或者对应克隆对象叫做继承对象)是谁啊?A.prototype对象,那A的继承父类是谁啊?Function.prototype,对象中的_proto_属性用来指向对象的继承父类。最难理解的一点:如果前面说的对的话,那Function的原型对象是谁?Function.prototype,Function对象的继承对象是谁?Function.prototype对象(定理1,2)  对此我得出以下观点:

  1.  b克隆的A,A克隆的Function,Function克隆的Function (这个绝对不是原型链)
  2.  b._prototype_指向A.prototype ,A._prototype_指向function.prototype,Function._proto_指向Function.prototype(这个也不是原型链)
  3.  b._prototype_指向A.prototype, A.prototype._proto_指向Object.prototype,Object.prototype._proto_指向null  (这才是b的原型链)
  4.  怎样证明一个b对象没有name属性? 就是顺着  b._prototype_._prototype_._prototype_都指向null了还没找到name属性,那就是没有name属性了

 我当初理解原型对象的时候有一个巨大的问题,我明明就 function A (){};我就自己定义了一个函数对象啊,A.prototype对象哪来的啊,确定有这个对象吗?

我在javascript语言精粹修订版(P22)似乎找到了答案,原文如下:

每个对象都连接到一个原型对象,并且它可以从中继承属性。所有通过对象字面量创建的对象都连接到Object.prototype,它是javascript中的标配对象。当你创建一个新对象时,你可以选择某个对象作为它的原型。javascript提供的实现机制杂乱而复杂(这个翻译我给满分,何必呢),但其实可以被明显地简化。我们将Object增加一个create方法。这个方法创建一个使用原对象作为其原型的新对象

注意了,见证奇迹的时刻到了:

if (typeof Object.beget !== 'function'){
    Object .create = function () {};
        var F = function () {};
        F.prototype = o;
        return new F();
    };
}

var another_stooge = Object.create(stooge);

 伟大的Douglas Crockford(道格拉斯·克罗克福德  javascript语言精粹的作者),他拯救了被javascript淹死的人,通过段代码,我们了解了创建一个对象时发生了什么,这下我们可以很确定的认为,每创建一个对象,他就有一个原型对象,既然真的有一个原型对象,那有人能理解定理5,6,8了吗?

 

就算你还不理解或者是还不认同,那么我还有一个更加形象的东西,给大家看一张我昨晚找到的最最美丽的一张图片

看完这张图,你是不是觉得自己似乎已经抓住了原型模式的命脉了吗?

我有一些问题

  1. 如果按照上图的关系,f1的原型链是什么,你能写出来吗?o2呢?
  2. 为什么function Foo,function Object, function Function的_proto_属性都指向Function.prototype?
  3. 你能理解为什么function Function 的_proto_属性和Prototype属性都指向Function.prototype对象吗?
  4. 为什么所有的Foo.prototype,Function.prototype对象的_proto_都指向Object.prototype?
  5. 如果我把function Foo.prototype = new Object();  var f3 = new Foo();f3的原型链你能写出来吗? f3._proto_==f1._proto_  的结果是 true Or false?
  6. Function instanceof Object 结果是什么呢?Object instanceof Function 的结果呢?(补充的那篇文章中有详细解释,不敢班门弄斧)
  7. 我上面认为的定理都对吗?或者哪里错了?

 

我本来应该先把这张图给大家看,然后围绕着这张图解释原型,但是我觉得那样有点知道了答案推过程,这样不太好,我们还是应该自己从最基础的理解做起,然后一步一步得到答案

看了许多博客文章,感激不尽,太多了就不一一列举,大家一搜就有。但是附上一个我觉得很关键的一篇文章,如果大家觉得我讲的不对或者不理解,可以看看这个文章,受益匪浅

 补充:

JavaScript instanceof 运算符深入剖析(建议收藏!)

希望对大家有用!同时也希望大家多多指点,让我更加深入的了解原型模式!

posted @ 2015-10-26 15:23  dogsmall  阅读(1534)  评论(1编辑  收藏  举报