深刻理解下js的prototype

参考
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

2

3

4

5

6

7

8

9

10

11

function
Animal() {}

function
Dog() {}

// 要让 Dog 继承 Animal, 只需:

Dog.prototype.__proto__ == Animal.prototype;

// 实例化后

var
dog = new
Dog();

// dog.__proto__ 指向 Dog.prototype

// dog.__proto__.__proto__ 指向 Animal.prototype

// 原型链已成功建立起来,而且很清晰

  

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

function
Animal(name) {

   this.name = name;

}

Animal.prototype = {

    talk: function() {},

    run: function() {}

}

function
Dog(age,name) {

   //Animal.call(this,name) 

   this.age=age;

}

// 要让 Dog 继承 Animal, 只需:__ 2个_

Dog.prototype.__proto__ =  Animal.prototype ; // 实例化后

//Dog.prototype = new  Animal ; //Animal的构造函数和自己的prototype也都放到Dog上

Dog.prototype.haha = function
() {};//

Dog.prototype.haha.tata = 4;

var
dog = new
Dog("sdd","bbb");

var
animal = new
Animal("aaaa");

console.log(dog);

console.log(Dog.prototype);

console.log(animal.__proto__);

console.log("11 "+(dog instanceof
Animal));

console.log("11 "+(animal instanceof
Dog));

  

Dog {name: "sdd", talk: function, run: function}

  1. name: "sdd"

  2. __proto__: Dog

    1. constructor: function
      Dog(name) {

      1. arguments: null

      2. caller: null

      3. length: 1

      4. name: "Dog"

      5. prototype: Dog

      6. __proto__: function Empty() {}

      7. <function scope>

    2. __proto__: Object

      1. run: function
        () {}

      2. talk: function
        () {}

      3. __proto__: Object

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

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

如果不加__proto__


function Animal(name) {
this.name = name;
}
Animal.prototype = {
talk: function() {},
run: function() {}
}
function Dog(name) {
Animal.call(this,name)
}
// 要让 Dog 继承 Animal, 只需:
Dog.prototype = Animal.prototype;

// 实例化后
var dog = new Dog("sdd");
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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

function
Animal(name) {

   this.name = name;

}

Animal.prototype = {

    talk: function() {},

    run: function() {}

}

function
Dog(name) {

    Animal.call(this,name) 

}

// 要让 Dog 继承 Animal, 只需:

Dog.prototype = Animal.prototype;//有没有有__proto__都会被覆盖

Dog.prototype = {

    qqq: function() {},

    wwww: function() {}

}

// 实例化后

var
dog = new
Dog("sdd");

console.log(dog);

console.log(dog instanceof
Animal );

  


Dog {name: "sdd", qqq: function, wwww: function}
name: "sdd"
__proto__: Object
  qqq: function () {}
  wwww: function () {}
  __proto__: Object

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

2,使用new

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

function
Animal(name) {

   this.name = name;

}

Animal.prototype = {

    talk: function() {},

    run: function() {}

}

function
Dog(age,name) {

   //Animal.call(this,name) 

   this.age=age;

}

// 要让 Dog 继承 Animal, 只需:__ 2个_

//Dog.prototype.__proto__ =  Animal.prototype ; // 实例化后

Dog.prototype = new 
Animal ; //Animal的构造函数和自己的prototype也都放到Dog上

Dog.prototype.haha = function
() {};

var
dog = new
Dog("sdd","bbb");

var
animal = new
Animal("aaaa");

console.log(dog);

console.log(dog.__proto__);

console.log(animal.__proto__);

console.log(dog.__proto__===Dog.prototype);

 


Dog {age: "sdd", name: undefined, haha: function, talk: function, run: function}
age: "sdd"
__proto__: Animal
  haha: function () {}
  name: undefined
  __proto__: Object
    run: function () {}
    talk: function () {}
    __proto__: Object

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

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

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


function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
this.getName = function (){};
}

var dog = new Dog("sdd","bbb");

console.log(dog);

//结果

Dog {age: "sdd", getName: function}
age: "sdd"
getName: function (){}
__proto__: Dog
constructor: function Dog(age,name) {
__proto__: Object


constructor: function Dog(age,name) {
arguments: null
caller: null
length: 2
name: "Dog"
prototype: Dog
__proto__: function Empty() {}
<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

2

3

4

5

6

7

8

9

Dog {age: "sdd", name: undefined, haha: function, talk: function, run: function}

age: "sdd"

__proto__: Animal

    haha: function
() {}

    name: undefined

    __proto__: Object

        run: function
() {}

        talk: function
() {}

        __proto__: Object           

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

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


run: function () {}
arguments: null
caller: null
length: 0
name: ""
prototype: Object
constructor: function () {}
__proto__: Object
__proto__: function Empty() {}

?





1

2

3

4

5

6

7

var
AAA= function(name) {

    this.name=222; 

}

AAA.dhj="123";

AAA.prototype.www=function(){};

var
aaa=new
AAA();

console.log(aaa);

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


AAA {name: 222, www: function}
name: 222
__proto__: Object
constructor: function (name) {
www: function (){}
__proto__: Object

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

下面分析下constructor

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

function
Animal(name) {

   this.name = name;

   var
a=1;

}

Animal.prototype.talk=function(){};

var
animal = new
Animal("aaaa");

function
Dog(age,name) {

   //Animal.call(this,name) 

   this.age=age;

   this.getName = function
(){};

}

// 要让 Dog 继承 Animal, 只需:__ 2个_

//Dog.prototype.__proto__ =  Animal.prototype ; // 实例化后

Dog.prototype = animal ; //注意这里啊,

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);

  


Dog {age: "sdd", getName: function, name: "aaaa", constructor: function, talk: function}
age: "sdd"
getName: function (){}
__proto__: Animal

function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
this.getName = function (){};
}

Animal {name: "aaaa", constructor: function, talk: function}
constructor: function Dog(age,name) {
name: "aaaa"
__proto__: Animal

function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
this.getName = function (){};
}

深刻理解下js的prototype

时间: 2024-10-25 10:41:56

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

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

我们可使用web3.js框架的estimateGas函数获得一个以太坊智能合约的Gas估计值 ,通过执行一个消息调用或交易,该消息调用或交易直接在节点的VM中执行,并未在区块链中确认,函数会返回估算使用的gas量. 函数调用: web3.eth.estimateGas(callObject [, callback]) 参数: 在 web3.eth.sendTransaction 中, 参数大都是可选的. 1. Object - 要发送的交易对象: from: String - 用来传送的账户地址

简单理解js的prototype属性

在进入正文之前,我得先说说我认识js的prototype这个东西的曲折过程. 百度js的prototype的文章,先看看,W3School关于prototype的介绍: 你觉得这概念适合定义js的prototype这个东西吗?你是否也认为prototype是一个object对象的属性呢?是的话,请认真认真看我这篇文章,因为这篇文章会毁灭你的人生三观,呵呵,就是有这么严重,因为本人就是被这个定义给害惨的. 不得不说,看了网上的一些介绍prototype的文章,基本上都说prototype是对象的一

js:深入prototype(下:原型重写)

//当属性和方法特别多时,编写起来不是很方便,可以通过json的格式来编写 //由于原型重写,而且没有通过Person.prototype来指定,此时的constructor不会再指向Person而是指向Object //如果constructor真的比较重要,可以在json中说明原型的指向 function Person(){ } Person.prototype = { //constructor:Person,   //手动指定constructor name:"octopus"

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

上一篇讲了js的prototype概念,在这里回顾一下prototype的定义: prototype是函数的一个属性,并且是函数的原型对象.引用它的必然是函数,这个应该记住. 但是,很奇怪,各位看官,你有没有看过类似下面这样引用prototype的js代码: function func(){ var args = Array.prototype.slice.call(arguments, 1); return args; } 咦???看着上面这行代码,你是不是对prototype只是属于函数产生

深刻理解JavaScript基于原型的面向对象

主题一.原型 一.基于原型的语言的特点 1 只有对象,没有类;对象继承对象,而不是类继承类. 2  "原型对象"是基于原型语言的核心概念.原型对象是新对象的模板,它将自身的属性共享给新对象.一个对象不但可以享有自己创建时和运行时定义的属性,而且可以享有原型对象的属性. 3 除了语言原生的顶级对象,每一个对象都有自己的原型对象,所有对象构成一个树状的层级系统.root节点的顶层对象是一个语言原生的对象,其他所有对象都直接或间接继承它的属性. 显然,基于原型的语言比基于类的语言简单得多,我

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

理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时间的考验.函数.闭包等特性使Javascript成为一门适合Web开发的理想语言. 有一种偏见认为Javascript是不可靠的,然而事实并非如此.人们对Javascript的偏见来源于DOM,DOM是浏览器厂商提供的用于Javascript与浏览器交互的API,不同浏览器厂商实现的DOM存在差异.

JS的prototype

初步理解: 在说prototype和constructor之前我们先得看几个例子. 1 2 3 4 function name(obj){     alert(obj)//"uw3c" } name("uw3c") 这是个普通的自调用的例子,大家都能理解,那么看下一个例子: 1 2 3 4 5 function name(obj){     alert(obj)//"uw3c" } var test = new name("uw3c&q

关于JS的prototype

在接触JS的过程中,随着理解的深入会逐渐的理解一些比较深奥的理论或者知识,那么今天我们来介绍一下比较难理解的prototype和constructor. 初步理解: 在说prototype和constructor之前我们先得看几个例子. function name(obj){ alert(obj)//"uw3c" } name("uw3c") 这是个普通的自调用的例子,大家都能理解,那么看下一个例子: function name(obj){ alert(obj)//

深刻理解Nginx之Nginx完整安装

1.   Nginx安装 1.1预先准备 CentOS系统下,安装Nginx的库包依赖.安装命令如下: sudo yum groupinstall "DevelopmentTools" sudo yum install pcre pcre-devel sudo yum install zlib zlib-devel yum install perl-ExtUtils-Embed sudo yum install openssl openssl-devel 1.2 安装 最重要的特性和基