首页 > 网站 > WEB开发 > 正文

深刻理解下js的prototype

2024-04-27 14:23:42
字体:
来源:转载
供稿:网友

深刻理解下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__

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

  

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。

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

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下才能展示出来下面的结构。

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: nullcaller: nulllength: 0name: ""prototype: Object    constructor: function () {}    __proto__: Object__proto__: function Empty() {}
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__: Objectconstructor: 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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表