参考 http://aralejs.org/class/docs/competitors.html, http://www.iteye.com/topic/248933,http://www.cnblogs.com/qiantuwuliang/archive/2011/01/08/1930548.html

1、使用Dog.prototype.__proto__

  1. function Animal() {}
  2. function Dog() {}
  3.  
  4. // 要让 Dog 继承 Animal, 只需:
  5. Dog.prototype.__proto__ == Animal.prototype;
  6.  
  7. // 实例化后
  8. var dog = new Dog();
  9. // dog.__proto__ 指向 Dog.prototype
  10. // dog.__proto__.__proto__ 指向 Animal.prototype
  11. // 原型链已成功建立起来,而且很清晰

  

  1. function Animal(name) {
  2. this.name = name;
  3. }
  4. Animal.prototype = {
  5. talk: function() {},
  6. run: function() {}
  7. }
  8. function Dog(age,name) {
  9. //Animal.call(this,name)
  10. this.age=age;
  11. }
  12. // 要让 Dog 继承 Animal, 只需:__ 2个_
  13. Dog.prototype.__proto__ = Animal.prototype ; // 实例化后
  14. //Dog.prototype = new Animal ; //Animal的构造函数和自己的prototype也都放到Dog上
  15. Dog.prototype.haha = function () {};//
  16. Dog.prototype.haha.tata = 4;
  17. var dog = new Dog("sdd","bbb");
  18. var animal = new Animal("aaaa");
  19. console.log(dog);
  20. console.log(Dog.prototype);
  21. console.log(animal.__proto__);
  22.  
  23. console.log("11 "+(dog instanceof Animal));
  24. console.log("11 "+(animal instanceof Dog));

  

  1.  
  2. Dog {name: "sdd", talk: function, run: function}
  3.  
  4. name: "sdd"
  5. __proto__: Dog
  6.  
  7. constructor: function Dog(name) {
  8.  
  9. arguments: null
  10. caller: null
  11. length: 1
  12. name: "Dog"
  13. prototype: Dog
  14. __proto__: function Empty() {}
  15. <function scope>
  16.  
  17. __proto__: Object
  18.  
  19. run: function () {}
  20. talk: function () {}
  21. __proto__: Object

__proto__指向了dog本身,并且有constructor,开始循环引用了。dog.__proto__=Dog.prototype。

dog本身的Dog.prototype没有被覆盖,一个标准的prototype,包括constructor和__proto__,我们只覆盖了这个标准的prototype的__proto__而已。

如果不加__proto__

  1. function Animal(name) {
  2. this.name = name;
  3. }
  4. Animal.prototype = {
  5. talk: function() {},
  6. run: function() {}
  7. }
  8. function Dog(name) {
  9. Animal.call(this,name)
  10. }
  11. // 要让 Dog 继承 Animal, 只需:
  12. Dog.prototype = Animal.prototype;
  13.  
  14. // 实例化后
  15. var dog = new Dog("sdd");
  16. console.log(dog);

 返回

Dog {name: "sdd", talk: function, run: function}
  1. name: "sdd"
  2. __proto__: Object
    1. run: function () {}
    2. talk: function () {}
    3. __proto__: Object

第二种原型链没有建立,没有constructor,只是简单的把方法赋值过来了。上面用 console.log(dog instanceof Animal ) 都返回ture。

  1. function Animal(name) {
  2. this.name = name;
  3. }
  4. Animal.prototype = {
  5. talk: function() {},
  6. run: function() {}
  7. }
  8. function Dog(name) {
  9. Animal.call(this,name)
  10. }
  11. // 要让 Dog 继承 Animal, 只需:
  12. Dog.prototype = Animal.prototype;//有没有有__proto__都会被覆盖
  13. Dog.prototype = {
  14. qqq: function() {},
  15. wwww: function() {}
  16. }
  17.  
  18. // 实例化后
  19. var dog = new Dog("sdd");
  20. console.log(dog);
  21. console.log(dog instanceof Animal );

  

  1. Dog {name: "sdd", qqq: function, wwww: function}
  2. name: "sdd"
  3. __proto__: Object
  4.   qqq: function () {}
  5.   wwww: function () {}
  6.   __proto__: Object

 Dog.prototype被覆盖了,本身的constructor和__proto__不存在了,变 Animal.prototype了。

2,使用new

  1. function Animal(name) {
  2. this.name = name;
  3. }
  4. Animal.prototype = {
  5. talk: function() {},
  6. run: function() {}
  7. }
  8. function Dog(age,name) {
  9. //Animal.call(this,name)
  10. this.age=age;
  11. }
  12. // 要让 Dog 继承 Animal, 只需:__ 2个_
  13. //Dog.prototype.__proto__ = Animal.prototype ; // 实例化后
  14. Dog.prototype = new Animal ; //Animal的构造函数和自己的prototype也都放到Dog上
  15. Dog.prototype.haha = function () {};
  16. var dog = new Dog("sdd","bbb");
  17. var animal = new Animal("aaaa");
  18. console.log(dog);
  19. console.log(dog.__proto__);
  20. console.log(animal.__proto__);
  21. console.log(dog.__proto__===Dog.prototype);

 

  1. Dog {age: "sdd", name: undefined, haha: function, talk: function, run: function}
  2. age: "sdd"
  3. __proto__: Animal
  4.   haha: function () {}
  5.   name: undefined
  6.   __proto__: Object
  7.     run: function () {}
  8.     talk: function () {}
  9.     __proto__: Object

new 是调用构造函数的,会把构造函数上的属性拿过来,没有constructor,只有new 带构造函数。__proto__是实例化后才有,他代表的原型链,可以共享的原型链,上图中方法haha 也放到__proto__中了。

Dog.prototype被覆盖了,本身的constructor和__proto__不存在了,变 new Animal了,于是构造函数都传过来了。

没有继承的情况下,如下图所示,prototype没有被覆盖,constructor保留,是Dog本身这个函数。dog.constructor === Dog.prototype.constructor

  1. function Dog(age,name) {
  2. //Animal.call(this,name)
  3. this.age=age;
  4. this.getName = function (){};
  5. }
  6.  
  7. var dog = new Dog("sdd","bbb");
  8.  
  9. console.log(dog);
  10.  
  11. //结果
  12.  
  13. Dog {age: "sdd", getName: function}
  14. age: "sdd"
  15. getName: function (){}
  16. __proto__: Dog
  17. constructor: function Dog(age,name) {
  18. __proto__: Object
  1. constructor: function Dog(age,name) {
  2. arguments: null
  3. caller: null
  4. length: 2
  5. name: "Dog"
  6. prototype: Dog
  7. __proto__: function Empty() {}
  8. <function scope>

按照《悟透javascript》书中说的,new形式创建对象的过程实际上可以分为三步:

第一步是建立一个新对象(叫A吧);

第二步将该对象(A)内置的原型对象设置为构造函数(就是Person)prototype 属性引用的那个原型对象;

第三步就是将该对象(A)作为this 参数调用构造函数(就是Person),完成成员设置等初始化工作。

其中第二步中出现了一个新名词就是内置的原型对象,注意这个新名词跟prototype对象不是一回事,为了区别我叫它inobj,inobj就指向了函数Person的prototype对象。在person的prototype对象中出现的任何属性或者函数都可以在one对象中直接使用,这个就是javascript中的原型继承了

总结: 1)Dog.prototype =  Animal.prototype 或者Dog.prototype.__proto__ =  Animal.prototype 时,dog instanceof Animal 都是true。Dog.prototype.__proto__ =  Animal.prototype,实际实例化后是      dog.__proto__.__proto__=Animal.prototype。沿着A的原型链查找 如果有一个原型和B.prototype相等 则返回true  , 如:A.__proto__.__proto__ === B.prototype 则返回true

     js的 instanceof 是根据什么来判断两个对象的继承关系?参考:http://yxc-gdut.iteye.com/blog/1812766

     js的instanceof是根据prototype来判断两个对象是否存在继承关系,A instanceof B, js会沿着A的原型链查找 直到找到A.__proto__ === B.prototype 返回true。

     一句话__proto__一层层都是指向继承的,最终到基本类型上。没有继承的就是他的protoype,包含constructor: function () {},__proto__: Object,和他自己加的方法。

     下图展示的new方法的,Dog.prototype = new  Animal ;所以dog第一层__proto__有name, new把构造函数有传入了。只有有prototype chrome下才能展示出来下面的结构。

  1. Dog {age: "sdd", name: undefined, haha: function, talk: function, run: function}
  2. age: "sdd"
  3. __proto__: Animal
  4. haha: function () {}
  5. name: undefined
  6. __proto__: Object
  7. run: function () {}
  8. talk: function () {}
  9. __proto__: Object

2)理解下function ,如下图。function ,包括 arguments, caller,length,name ,prototype,__proto__,他的prototype,又分为constructor: function () {},__proto__: Object,然后constructor这个function 又继续循环。

     __proto__他从别的原型链继承过来可以直接用的,prototype是他要加在自己原型链上的,供别人调用,或者直接实例化后,别人可以直接调用转成__proto__的。

  1. run: function () {}
  2. arguments: null
  3. caller: null
  4. length: 0
  5. name: ""
  6. prototype: Object
  7. constructor: function () {}
  8. __proto__: Object
  9. __proto__: function Empty() {}
  1. var AAA= function(name) {
  2. this.name=222;
  3. }
  4. AAA.dhj="123";
  5. AAA.prototype.www=function(){};
  6. var aaa=new AAA();
  7. console.log(aaa);

  有继承关系的__proto__他指向的是指定的继承的那个,没有继承关系的__proto__依然保留constructor: function () {},__proto__: Object。

  1. AAA {name: 222, www: function}
  2. name: 222
  3. __proto__: Object
  4. constructor: function (name) {
  5. www: function (){}
  6. __proto__: Object

按照javascript的说法,function定义的这个是一个Object(对象),而且还是一个很特殊的对象,这个使用function定义的对象与使用new操作符生成的对象之间有一个重要的区别。这个区别就是function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性prototype属性又指向了一个prototype对象,注意prototype属性prototype对象是两个不同的东西,要注意区别。在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身。

下面分析下constructor

  1. function Animal(name) {
  2. this.name = name;
  3. var a=1;
  4. }
  5. Animal.prototype.talk=function(){};
  6. var animal = new Animal("aaaa");
  7. function Dog(age,name) {
  8. //Animal.call(this,name)
  9. this.age=age;
  10. this.getName = function (){};
  11. }
  12. // 要让 Dog 继承 Animal, 只需:__ 2个_
  13. //Dog.prototype.__proto__ = Animal.prototype ; // 实例化后
  14. Dog.prototype = animal ; //注意这里啊,
  15. Dog.prototype.constructor = Dog;//animal本身也有constructor,animal本身也指定到这里。引用传递。animal已经实例化了
  1. var dog = new Dog("sdd","bbb"); console.log(dog); console.log(dog.constructor);; console.log(animal); console.log(animal.constructor);

  

  1. Dog {age: "sdd", getName: function, name: "aaaa", constructor: function, talk: function}
  2. age: "sdd"
  3. getName: function (){}
  4. __proto__: Animal
  5.  
  6. function Dog(age,name) {
  7. //Animal.call(this,name)
  8. this.age=age;
  9. this.getName = function (){};
  10. }
  11.  
  12. Animal {name: "aaaa", constructor: function, talk: function}
  13. constructor: function Dog(age,name) {
  14. name: "aaaa"
  15. __proto__: Animal
  16.  
  17. function Dog(age,name) {
  18. //Animal.call(this,name)
  19. this.age=age;
  20. this.getName = function (){};
  21. }

深刻理解下js的prototype的更多相关文章

  1. 再深刻理解下web3.js中estimateGas如何计算智能合约消耗的gas量

    我们可使用web3.js框架的estimateGas函数获得一个以太坊智能合约的Gas估计值 ,通过执行一个消息调用或交易,该消息调用或交易直接在节点的VM中执行,并未在区块链中确认,函数会返回估算使 ...

  2. 简单理解js的prototype属性

    在进入正文之前,我得先说说我认识js的prototype这个东西的曲折过程. 百度js的prototype的文章,先看看,W3School关于prototype的介绍: 你觉得这概念适合定义js的pr ...

  3. 深入理解js的prototype以及prototype的一些应用

    上一篇讲了js的prototype概念,在这里回顾一下prototype的定义: prototype是函数的一个属性,并且是函数的原型对象.引用它的必然是函数,这个应该记住. 但是,很奇怪,各位看官, ...

  4. js Array.prototype.join.call(arguments,",") 理解

    prototype 属性使您有能力向对象添加属性和方法. join() 方法:把数组的所有元素放入一个字符串.元素通过指定的分隔符进行分隔. call() 方法可以用来代替另一个对象调用一个方法. A ...

  5. 关于JS的prototype

    在接触JS的过程中,随着理解的深入会逐渐的理解一些比较深奥的理论或者知识,那么今天我们来介绍一下比较难理解的prototype和constructor. 初步理解: 在说prototype和const ...

  6. JS的prototype

    初步理解: 在说prototype和constructor之前我们先得看几个例子. 1 2 3 4 function name(obj){     alert(obj)//"uw3c&quo ...

  7. [译] 所有你需要知道的关于完全理解 Node.js 事件循环及其度量

    原文地址:All you need to know to really understand the Node.js Event Loop and its Metrics 原文作者:Daniel Kh ...

  8. Nodejs第一天-{Nodejs基础 深刻理解浏览器 环境变量 基础语法}

    Nodejs第一天 1.什么是Nodejs ​ Nodejs是一个可以运行(解析)ECMAScript的环境; ​ ECMAScript是规定了一些列的语法 ,这些语法想要解析的执行就需要放在某个环境 ...

  9. 方便大家学习的Node.js教程(一):理解Node.js

    理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时 ...

随机推荐

  1. [CQOI2014]通配符匹配

    Description 几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户.最常见的通配符有两个,一个是星号(""'),可以匹配0个及以上的任意字符:另一个 ...

  2. Iahub and Xors Codeforces - 341D

    二维线段树被卡M+T...于是去学二维树状数组区间更新区间查询 树状数组维护数列区间xor的修改.删除(就是把原问题改成一维): 以下p*i实际都指i个p相xor,即(i&1)*pa表示原数列 ...

  3. LCA UESTC 92 Journey

    题目传送门 题意:先给一棵树,然后有一条额外的边,问u走到v从现在最短的路走和原来不加边走的路节省了多少距离 分析:首先跑不加边的树的LCA,这样能求出任意两点的距离,那么现在x和y多连了一条边,如果 ...

  4. 线段树+扫描线 HDOJ 5091 Beam Cannon(大炮)

    题目链接 题意: 给出若干个点的坐标,用一个W*H的矩形去覆盖,问最多能覆盖几个点. 思路: 这是2014上海全国邀请赛的题目,以前写过,重新学习扫描线.首先把所有点移到第一象限([0, 40000] ...

  5. Squid启动报:Could not determine this machines public hostname. Please configure one or set 'visible_hostname'.

    在squid.conf中添加 visible_hostname squid.packet-pushers.net 或者编辑/etc/hosts文件, 在该文件中制定主机IP地址与主机名的对应.

  6. [转]Java中实现自定义的注解处理器

    Java中实现自定义的注解处理器(Annotation Processor) 置顶2016年07月25日 19:42:49 阅读数:9877 在之前的<简单实现ButterKnife的注解功能& ...

  7. poj1857 To Europe! To Europe!

    思路: 一维dp. 实现: #include <cstdio> #include <iostream> using namespace std; const int INF = ...

  8. 如何使用xftp工具在Windows与Linux之间传输文件

    如何使用xftp工具在Windows与Linux之间传输文件 整理者:vashon 声明:感谢开源社区 xftp工具是一款SFTP,FTP文件传输软件,可在Windows pc与Unix/Linux之 ...

  9. prevent to do sth 与 prevent sb (from) doing 用法

    prevent to do sth 如: Do not water in before making a turn every time 9 days, make wilting of its bra ...

  10. hdu 3232 Crossing Rivers 过河(数学期望)

    题意:你在点A,目的地是点B,A和B的距离为D.中间隔了好多条河(所有河不会重叠),每条河有3个参数(P,L,V),其中P表示距离A点的长度,L表示河的长度,V表示河里的船的速度.假设每条河中仅有1条 ...