zoukankan      html  css  js  c++  java
  • JavaScript基础之对象

    摘自:http://www.cnblogs.com/syuko/archive/2008/03/05/1091843.html  

    从2004年下半年开始学习Web编程至今3年有余。从HTML,asp开始到现在的VS2008一路学过来,其中学的最多的还是服务器端编程,对客户端编程的学习还是不成系统。虽然在很多个系统里面应用过脚本,有些还起到了比较重要的作用。但一直是只知其然不知其所以然,用的是小心翼翼。现在脚本编程从以前的"雕虫小技"变成了一个Web开发不可或缺的元素,其地位大大提高了,特别是Ajax兴起之后它更是"炙手可热"了。鉴于此种情况及自己对脚本编程的热爱,于是就系统地学习一下脚本。

        学习是理解和记忆的过程。在理解和记忆的过程中必不可少地就需要一些辅助的记录,于是我就将自己的学习记录写成随笔。一来是帮助自己理解和记忆,二来也给其它热爱脚本的同志一些参考。

     1 JavaScript对象

        ECMA-262将对象(object)定义为"属性的无序集合,每个属性存放一个原始值、对象或函数"(unordered collection of properties each of which contains a primitive value, object, or function)。这意味着对象是无特定顺序的值的数组。在ECMAScript中,对象由特性(Attribute)构成,特性可以是原始值,也可以是引用值。如果特性存放的是函数,它将被看作对象的方法(Method),否则该特性被看作属性(Property)。

    2 对象的废除

        ECMAScript有无用存储单元收集程序(就像C#的垃圾收集器)意味着不必专门销毁对象来释放内存。当再没有对对象的引用时,该对象就被废除了。运行无用存储单元收集程序时,所有废除的对象都会被销毁。每当函数执行完它的代码,无用存储单元收集程序都会运行,释放所有的局部变量,还有在一些其它不可预知的情况下,无用存储单元收集程序也会运行。
       
    把对象的所有引用都设置为null,可以强制性的废除对象。例如:

        Var oObject=new Object();

        // 程序逻辑

        oObject=null;

        当变量oObject设置为null后,对第一个创建的对象的引用就不存在了。这意味着下次运行无用存储单元收集程序时,该对象将被销毁。 
        
    每用完一个对象后,就将其废除,来释放内存,这是个好习惯。这样还确保不再使用已经不能访问的对象,从而防止程序设计错误的出现。此外,旧的浏览器(如IE)没有完全的无用存储单元收集程序,所以卸载页面时,对象可能不能被正确地销毁。以前IE6就有这样的诟病,当页面被关闭后对象还是没有被释放,所以总是会导致内存溢出的错误。废除对象和它所有的特性是确保内存正确使用的最好方法。

    3 对象的类型

        JavaScript中对象分为:本地对象(native object)、内置对象(built-in object)、宿主对象(host object)。其中本地对象和宿主对象大家一般用的比较多,比较熟。这里我就重点说明一下内置对象。 
        
    ECMA-262把内置对象定义为"由ECMAScript实现提供的、独立于宿主环境的所有对象,在ECMAScript程序开始执行时出现"(any object supplied by an ECMAScript implementation, independent of the host environment, which is present at the start of the execution of an ECMAScript program.)。这意味着开发者不必明确实例化内置对象,它已经被实例化了。但ECMAScript只定义了两个内置对象:

    3.1 Math对象

        Math对象就是解决数学问题的所有公式。这个在各种编程语言中都有类似的实现,就不做介绍了。

    3.2 Global对象

        园子里很多搞ASP.net的,相信大家对其中的Global.asax非常熟悉了。但这个对象在ECMAScript中却比较特殊。因为它实际上根本就不存在。如果尝试编写下面的代码去实例化它,将得到错误: 
        
    Var _global=new Global(); 
        
    错误消息显示Global不是对象,但上文却说Global是一个内置对象,这不就自相矛盾了吗?不矛盾。这里需要理解的主要概念是,在ECMAScript中,不存在独立的函数,所有的函数都必须是某个对象的方法。ECMAScript中常用的函数例如isNaN()、isFinite()等,看起来都像独立的函数。实际上,它们都是Global对象的方法。而且Global对象的方法还不止这些。

    4 定义类或对象

        虽然ECMAScript越来越正规化了,但创建对象的方法却被置之不理。在高级的编程语言(如C#)中,创建对象的方法被明确的定义了。所以不会有太大的分歧。但在脚本语言中创建对象的方法就是多种多样了。

    4.1 工厂方式

    由于对象的属性可在对象创建后动态定义,所以许多开发者都在初次引入JavaScript时编写类似下面的代码: 
        
    Var oCar=new Object(); 
        
    oCar.color="red"; 
        
    oCar.doors=4; 
        
    oCar.mpg=23; 
        
    oCar.showColor=function(){alert(this.color);}; 
        在这段代码中,创建对象car。然后给它设置几个属性:它的颜色是红色,有四个门,每加仑油23英里。最后一个属性是指向函数的指针,意味着该属性其实是个方法。执行这段代码后,就可以使用对象car了。可是要创建多个car实例就麻烦了。 
        
    要解决此问题,开发者可以创建并返回特定类型的对象的工厂函数。例如,函数CreateCar()可用于封装前面列出的创建car对象的操作: 
        
    Function createCar() 
        

            
    Var oTempCar=new Object(); 
            
    oTempCar.color="red"; 
            
    oTempCar.doors=4; 
            
    oTempCar.mpg=23; 
            
    oTempCar.showColor=function(){alert(this.color)};
        
            
    return oTempCar; 
        


        Var oCar1=createCar(); 
        
    Var oCar2=createCar();

        这里,前面的所有代码都包含在createCar()函数中,此外还有一行额外的代码,返回Car对象作为函数值。调用此函数时,将创建新对象,并赋予它所有必要的属性,复制出一个前面说明的car对象。使用该方法,可以容易地创建car对象的两个版本,他们的属性完全一样。当然,还可以修改creatCar()函数,给它传递各个属性的默认值,而不是赋予属性默认值: 
        
    Function createCar(sColor,iDoors,iMpg) 
        

            
    Var oTempCar=new Object(); 
            
    oTempCar.color= sColor; 
            
    oTempCar.doors= iDoors; 
            
    oTempCar.mpg= iMpg; 
            
    oTempCar.showColor=function(){alert(this.color)};

            return oTempCar; 
        

        
        
    Var oCar1=createCar("red",4,23); 
        
    Var oCar2=createCar("blue",2,26); 
        
    oCar1.showColor();            // 输出"red" 
        
    oCar2.showColor();            // 输出"blue"

        给createCar()函数加上参数,即可为要创建的car对象的color、doors和mpg属性赋值。使这两个对象具有相同的属性,却有不同的属性值。但这里有个问题:每次调用函数createCar(),都要创建新函数showColor(),意味着每个对象都有自己的showColor()版本。事实上,每个对象用的都是同一段代码。这样的定义方法还有一个如下的变形:
        Function Car(sColor,iDoors,iMpg) 
        

            
    this.color= sColor; 
            
    this.doors= iDoors; 
            
    this.mpg= iMpg; 
            
    this.showColor=function(){alert(this.color)}; 
        
    }

        Var oCar1=new Car("red",4,23); 
        
    Var oCar2=new Car("blue",2,26);

        oCar1.showColor();            // 输出"red" 
        
    oCar2.showColor();            // 输出"blue" 
        这个方法和上一个方法有个一样的缺陷:重复的创建了showColor()函数。为了解决这个缺陷我们可以用下面的方法。

    4.2 原型方式

        该方法利用了对象的Prototype属性。用空构造函数来设置类名,然后所有的属性和方法都被直接赋予prototype属性: 
        
    Function Car() 
        
    {} 

        
    Car.prototype.color="red"; 
        
    Car.prototype.doors=4;
        
    Car.prototype.mpg=23; 
        
    Car.prototype.showColor=function(){alert(this.color)};

         Var oCar1=new Car(); 
        
    Var oCar2=new Car();

        使用这个方法可以解决重复创建showColor()函数,但又会有新的问题,考虑下面的例子: 

        
    Function Car() 
        
    {} 

        
    Car.prototype.color="red"; 
        
    Car.prototype.doors=4; 
        
    Car.prototype.mpg=23; 
        
    Car.prototype.drivers=new Array("Mike","Sue"); 
        
    Car.prototype.showColor=function(){alert(this.color)};

         Var oCar1=new Car(); 
        
    Var oCar2=new Car();

        oCar1.drivers.push("Matt"); 

        
    alert(oCar1.drivers);        // 输出"Mike,Sue,Matt" 
        
    alert(oCar2.drivers);        // 输出"Mike,Sue,Matt"

        这里,属性drivers是指向Array对象的指针。改变指针指向的内容,所有的实例都会改变。看来这种方法也不可取

        4.3 混合方式

        这种方式就是用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。结果所有的函数只创建一次,而每个对象都具有自己的对象属性实例。 
        
    Function Car(sColor,iDoors,iMpg) 
        

            
    this.color= sColor; 
            
    this.doors= iDoors;

    this.mpg= iMpg;
    Car.drivers=new Array("Mike","Sue");
    }

    Car.prototype.showColor=function(){alert(this.color)};

    Var oCar1=new Car("red",4,23);
    Var oCar2=new Car("blue",3,25);

    oCar1.drivers.push("Matt");

    alert(oCar1.drivers);        // 输出"Mike,Sue,Matt"
    alert(oCar2.drivers);        // 输出"Mike,Sue"

    这种方式是ECMAScript主要采用的方式,它具有其他方式的特性,却没有它们的缺陷。在实际编程中应用的也是最多了。 
    另外还有JSON创建方式。其创建的方式如下:

    var Car =

        
    color: "red", 
        
    doors: 4, 
        
    mpg: 23, 
        drivers: [{name: "Mike", age: 20, Married: false}, {name: "Sue", age: 30, Marred: true}],
        showColor: function() {alert(this.color)}
    };
    这种创建对象的方式也比较优雅。可作为Ajax返回的文本,然后用eval()函数将其还原成一个对象。著名的脚本框架JQuery就有专门接收返回文本为JSON对象的异步方法。

  • 相关阅读:
    《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该恰好瓜还是恰坏瓜
    《Machine Learning in Action》—— 女同学问Taoye,KNN应该怎么玩才能通关
    《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”
    深度学习炼丹术 —— Taoye不讲码德,又水文了,居然写感知器这么简单的内容
    《Machine Learning in Action》—— 浅谈线性回归的那些事
    《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非线性支持向量机
    《Machine Learning in Action》—— hao朋友,快来玩啊,决策树呦
    《Machine Learning in Action》—— 剖析支持向量机,优化SMO
    《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM
    JVM 字节码指令
  • 原文地址:https://www.cnblogs.com/blsong/p/1662522.html
Copyright © 2011-2022 走看看