zoukankan      html  css  js  c++  java
  • js原型

    1、js基本类型和对象类型
    js的简单类型包括数字(其中NaN为数字类型)、字符串(类似'A'为字符,js没字符类型)、布尔值、null值和undefined值。其他所有的值都是对象。数字、字符串和布尔值“貌似”是对象,因为它们拥有方法,但它们是不可变的,所以不是对象。js的对象时可变的键控集合(keyed collections)。在js中,数组、函数、正则表达式是对象。


    2、js原型的重要知识点
    首先要知道一个很重要的知识点,一句话:所有对象都有原型对象。


    3、对比其他语言的理解
    原型对象,就是其它语言中的类中的静态属性和静态方法,总之是静态-static就对了.原理是: 内存中只有一份。


    4、原型链
    每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性 时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样 一直找下去,也就是我们平时所说的原型链的概念。
    按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是火狐和谷歌(ie除外)的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。因为ie不存在__proto__属性,所以在ie中,当对象创建后,对象的原型链就已经确定,无法更改。
    由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefined.原型链一般实现为一个链表,这样就可以按照一定的顺序来查找。
    prototype是构造器原型,其实prototype只是一个假象,他在实现原型链中只是起到了一个辅助作用,换句话说,他只是在new的时候有着一定的价值,而原型链的本质,其实在于__proto__。实例如下:

     1 var base = { 
     2     name : "base", 
     3     getInfo : function(){ 
     4         return this.name; 
     5     } 
     6 } 
     7 
     8 var ext1 = { 
     9     id : 0, 
    10     __proto__ : base 
    11 } 
    12 
    13 var ext2 = { 
    14     id : 9, 
    15     __proto__ : base 
    16 } 
    17 
    18 document.write(ext1.id); 
    19 document.write(ext1.getInfo()); 
    20 document.write(ext2.id); 
    21 document.write(ext2.getInfo()); 

    结果:
    0
    base
    9
    base
    图1

    其中proto__属性在ie中无法看到,在谷歌、火狐浏览器的debug下能看到这个属性。上面实例在ie中,ext1.name为undefined。ie中,ext1的对象在debug中内部结构如下:

    在谷歌浏览器debug中内部结构如下:


    5、分析一(对象字面量)
    示例代码如下:

    1 var base = { 
    2       name : "base", 
    3       getInfo : function(){ 
    4             return this.name; 
    5       } 
    6 } 

    谷歌浏览器debug模式下base对象的内部结构如下:


    6、分析二(普通函数)
    示例代码如下:

    1 function test(){
    2      document.write("hello world");
    3 }

    谷歌浏览器debug模式下base对象的内部结构如下:


    7、分析三(构造函数)
    示例代码如下:

    1 function createObj(name){
    2      this.name = name;
    3 }

    var o3 = new createObj("yql");
    谷歌浏览器debug模式下base对象的内部结构如下:


    8、使用某对象作为原型的方法
    当你创建一个新对象时,你可以选择某个对象作为它的原型。js提供的实现机制杂乱而复杂,但其实它可以被明显的简化。我们将给Object增加一个beget方法,这个方法创建一个使用原对象作为其原型的新对象。示例代码如下:

     1 if(typeof Object.beget !== 'function'){
     2     Object.beget = function(obj){
     3        var F = function(){};
     4        F.prototype = obj;//__proto__属性在ie中不存在,只能通过构造函数的prototype来设置原型
     5        return new F();
     6     };
     7 }
     8 var obj = {
     9       msg:"hello world"
    10 };
    11 var newObj = Object.beget(obj);
    12 document.write(newObj.msg);//hello world

    谷歌浏览器debug模式下base对象的内部结构如下:

    ie浏览器debug模式下base对象的内部结构如下:


    9、我的理解
    示例一:

    1 var obj = {
    2       name : "zhangsan"
    3 };
    4 document.write(obj.name)//zhangsan
    5 document.write(obj.age)//undefiend
    6 Object.prototype.age = 28;
    7 document.write(obj.age);//28

    示例二:

    function ObjConstructor(name){
         this.name = name;
    }
    var obj = new ObjConstructor("zhangsan");
    document.write(obj.name+"<br />");//zhangsan
    document.write(obj.age+"<br />");//undefiend
    ObjConstructor.prototype.age = 28;
    Function.prototype.sex = "M";
    Object.prototype.home = "hb";
    document.write(obj.age+"<br />");//28,obj.__proto__===ObjConstructor.prototype,即obj的原型为ObjConstructor.prototype对象
    document.write(obj.sex+"<br />");//undefined,说明对象obj不能访问到Function.prototype
    document.write(obj.home+"<br />");//hb,obj的原型的原型为Obj.prototype对象

    示例三:

    1 var str = new String();
    2 document.write(str.name);//undefined
    3 String.prototype.name="zhangsan";
    4 Object.prototype.age = 28;
    5 Function.prototype.sex = "M";
    6 document.write(str.name);//zhangsan,str的原型指向String.prototype对象
    7 document.write(str.age);//28,str的原型的原型指向Object.prototype对象
    8 document.write(str.sex);//undefined,str的原型链中没有指向Function.prototype对象

    根据上面3个示例,可以得出以下几点内容:
    1、对象在构造时,js引擎会设定该对象的原型(虽然谷歌、火狐的浏览器下可以修改对象原型的指向,但是ie中无法修改,而且按照标准,原型为隐藏的,不推荐可以修改)。对象构造完成后,对象的原型指向
    的对象无法更改。如示例一中obj的原型指向Object.prototype对象,示例二中obj的原型指向ObjConstructor.prototype对象,示例三中str的原型指向String.prototype对象,这3个对象的原型指向的对象不能修改为
    其他对象,只能是对应构造函数的prototype指向的对象。
    2、只有函数有prototype属性,普通对象没有prototype属性。对象构造后,对象的原型指向其构造函数的prototype属性的对象。如示例一中obj的构造函数为function Object(){...},示例二中obj的构造函数为
    function ObjConstructor(name){...},示例三中str的构造函数为function String(){...},所以他们的原型指向分别为Object.prototype对象、ObjConstructor.prototype对象和String.prototype对象。
    3、自定义的函数的构造函数为function Function(){...},所以自定义的函数的原型为Function.prototype对象。如示例二中ObjConstructor的原型指向Function.prototype对象。
    4、构造函数的prototype属性指向普通对象(不是函数),所以构造函数.prototype对象的原型为Object.prototype(不包括多层构造的情况)。如示例二中ObjConstructor.prototype的原型为Object.prototype
    5、__proto__属性为对象(包括函数)的原型属性(ie中该属性为隐藏,按标准,该属性应该为隐藏的,但是可以用该属性来理解原型),prototype为函数的属性。当使用构造函数构造对象后,对象的原型
    (即对象.__proto__)为构造函数的prototype(构造函数.prototype)所指向的对象。 容易理解错误的是,虽然对象的原型与prototype有紧密的联系,但是对象的原型不是对象的prototype属性。
    6、按照java语言,可以这样理解:构造函数为类,所以推荐构造函数名称首字母大写。对象的原型的属性或方法可以理解为类的属性或方法(即java类中用static修饰的属性或方法)。

  • 相关阅读:
    ActionBarSherlock学习笔记——知识点
    ActionBarSherlock学习笔记——SubMenu
    Android解析xml——pull
    ActionBarSherlock学习笔记——ShareActionProvider
    Listview下拉刷新(顶部刷新)
    ActionBarSherlock学习笔记——SupportActionBar()属性设置
    ActionBarSherlock学习笔记——ActionBar.Tab
    ActionBarSherlock学习笔记——SearchView
    ActionBarSherlock学习笔记——requestWindowFeature
    ActionBarSherlock学习笔记——ActionBar添加View
  • 原文地址:https://www.cnblogs.com/yuyuj/p/4525482.html
Copyright © 2011-2022 走看看