JavaScript原型从入门到精通

来源:互联网 发布:如何网络共享文件夹 编辑:程序博客网 时间:2024/06/14 16:49

JavaScript原型从入门到精通

ps:原型里面涉及的到的各种属性单独讲解很难将通,所以一个属性经常会结合其他属性来理解(文章中如有错误,欢迎指正)

1.prototype属性

当我们创建一个函数的时候,这个函数就会具有一个原型(prototype)属性,所以只有函数才会有prototype属性

function Book(Name, Version){this.Name = Name;this.Version = version;};                       //具有prototype属性var newBook = new Book("JavaScript", "V2.0");   //不具有prototype属性Book.prototype;                                 //Object{constructor:Book(),__proto__:Object}

Book函数的原型对象(也就是Book.prototype)里面又有constructor属性以及通过构造函数添加的其他方法(Name、Version)。原型对象(Book.prototype)里的constructor属性又指向prototype属性所在函数的指针(即Book函数,Book函数是一个函数名,也是一个指针),我们可以用一段代码来表示

Book.prototype.constructor === Book;

通过实例化创建一个新类(newBook)的时候,newBook不会有prototype属性,但是它的内部包含一个指针,指向构造函数(Book)的原型对象,这个指针在Firefox、Safari、Chrome浏览器有具体的实现,即__proto__(两边都是两个下划线),如下图

这里写图片描述

当通过new关键字实例化newBook类时,其实就是将newBook的内部属性(proto)指向了Book.prototype,即

 newBook.__proto__ === Book.prototype;               //仅在Firefox、Safari、Chrome调试有效

所以newBook实例本身不会包含Book的属性和方法,使用newBook.Name调用Name属性其实就是通过查找对象的过程来实现的

2.constructor属性

construcor属性用于返回创建该对象的函数,即构造函数。
Book的原型具有constructor属性,那么通过new实例化的对象是否也有constructor属性呢?
答案是肯定的,通过构造函数创建的对象都有两个隐藏属性,constructor属性和__proto__属性。在最开始的代码中,我们很容易就能知道newBook的constructor属性其实就是Book,因为构建newBook对象的函数就是Book函数,它的constructor当然就是Book对象了,即

var newBook = new Book("JavaScript", "V2.0");newBook.constructor === Book           //true

这里写图片描述

结合第一节(prototype属性),可以总结代码如下:

//文章中代码的结论newBook.constructor === Book;Book.prototype.constructor === Book;//推论Book.prototype.constructor === newBook.construcotr;       //true//文章中代码的结论(__proto__会在第三节详细讲)newBook.__proto__ === Book.prototype;//推论newBook.__proto__.constructor === Book;           //truenewBook.__proto__.constructor === newBook.construcotr;       //true

或许有的人会疑惑,Book函数的构造器又是什么?
我们可以通过以下代码来测试

 Book.constructor    //function Function(){} alert(Book.constructor === Function)     //true

即Book的构造函数是Function,因为创建Book的函数是Function函数,底层JavaScript是通过Function创建一个函数,所以任何通过function构造的函数的constructor属性都指向它,所以如下图

这里写图片描述

上述代码中Book.constructor返回的是functino Function(){},这说明在JS源码中,Function也是由function创建的,那么也就说明Function中具有constructor属性,而这个属性指向它本身,即

 Function.constructor === Function;       //true

这里写图片描述

又由第一节分析,创建函数时也会创建函数的prototype属性,所以Function也有prototype属性,那么Function的原型指向的是什么呢?

 Function.prototype              //function(){} 

这代表什么?(现在先不讲解)

3.__proto__属性

定义:当创建一个函数时,其内部将包含一个指针,指向构造函数的原型对象。
第一节已经讲过,__proto__属性在Firefox、Safari、Chrome浏览器有具体的实现,第二节也说过通过构造函数创建的对象都有两个隐藏属性,constructor属性和__proto__属性,那么我们就知道为什么第一节中Book.prototype为何会输出Object{constructor:Book(),__proto__:Object}了。
通过new关键字实例化对象时,也会创建相应的__proto__属性,且这个属性指向实例化的原型对象(即Book.prototype)
通过function关键字创建函数时,函数也会有__proto__属性,那么这个函数的__proto__属性指向什么呢?以一段测试代码来验证。

 newBook.__proto__ === Book.prototype;             //true Book.__proto__;                 //function(){}

为什么Book.proto会输出function(){ }?
根据 定义,我们就需要找到构造Book的函数,第二节已经给出了答案Function,那么指向构造函数的原型对象就是指向Function的原型,即Function.prototype,附代码验证

Book.__proto__ === Function.prototype        //第二节遗留问题      

这里写图片描述

再来测试一下Function的__proto__属性

Function.__proto__;                //function(){} ,那么是否与上面的Function.prototype,Book.__proto__相等呢Function.__proto__ === Function.prototype;   //trueFunction.__proto__ === Book.__proto__;       //true 

因为Function是最顶层的函数对象,没有比Function的原型更原型的了,所以Function.__proto__ === Function.prototype。

4.Object与Function

函数是一种对象,那么对象是什么呢?对象是否有prototype属性,__proto__属性以及constructor属性?

var Class = new Object;Class.__proto__;         //Object{}Class.prototype;         //undefinedClass.constructor;       //function Object(){}//对象字面量var Grade = {};Grade.__proto__;         //Object{}Grade.prototype;         //undefinedGrade.constructor;       //function Object(){}

分析代码结果,对象具有__proto__属性和constructor属性。因为函数是一种对象,我们就可以猜测函数与对象之间必定存在某种关联,那么究竟是什么样的关联呢?
分析: 从上述代码的结果中,我们可以看到,Class.constructor和Grade.constructor(因为两种形式结果相同,就拿其中一种来说明)输出的结果都是function Object(){ },结果是一种函数对象!!!而Class.__proto__的结果只是对象Object{ }。Class.__proto__指向构造函数的原型对象,上述代码中Class.__proto__的构造函数是Object,所以Class.__proto__指向Object的原型对象,即Object.prototype。

 Class.__proto__ === Object.protortype;              //true Object.prototype;               //Object{} 

这里写图片描述

再来看看Object对象

 Object;                 //function Object() { [native code] }    

可以看出Object是一种函数,那么它是否有函数应有的prototype和__proto__以及constructor属性呢

Object.prototype;           //Object{}Object.__proto__;           //function(){}Object.constructor;         //function Function(){} 

这里写图片描述

首先,Object的原型是它自己,说明Object是最顶层的对象。然后Object.proto指向构造函数的原型对象,从第二行代码看出Object.proto的构造函数是function的原型,而Object的构造函数是function,故

Object.__proto__ === Function.prototype;        //trueObject.constructor === Function;     //true    

所以总结第三节,得出结论

 Object.__proto__ === Function.prototype === Function.__proto__; Object.constructor === Function ==Function.constructor;

这里写图片描述

上图就是原型与构造函数个人总结的图(如有错误,欢迎指正,一起学习)。

原创粉丝点击