美文网首页
ECMAScript 面向对象

ECMAScript 面向对象

作者: 耦耦 | 来源:发表于2018-01-02 09:21 被阅读10次

    一、ECMAScript 面向对象技术


    1、面向对象语言的要求

    一种面向对象语言需要向开发者提供四种基本能力:

    • 封装 -- 把相关的信息(无论数据或方法)存储在对象中的能力
    • 聚集 -- 把一个对象存储在另一个对象内的能力
    • 继承 -- 由另一个类(或多个类)得来类的属性和方法的能力
    • 多态 -- 编写能以多种方法运行的函数或方法的能力
      ECMAScript 支持这些要求,因此可被是看做面向对象的。

    2、对象的构成

    在 ECMAScript 中,对象由特性(attribute)构成,特性可以是原始值,也可以是引用值。如果特性存放的是函数,它将被看作对象的方法(method),否则该特性被看作对象的属性(property)。

    二、ECMAScript 对象应用


    1、声明和实例化

    对象的创建方式是用关键字 new后面跟上实例化的类的名字:

    var oObject = new Object();
    var oStringObject = new String();
    

    第一行代码创建了 Object 类的一个实例,并把它存储到变量 oObject 中。第二行代码创建了 String 类的一个实例,把它存储在变量 oStringObject 中。如果构造函数无参数,括号则不是必需的。因此可以采用下面的形式重写上面的两行代码:

    var oObject = new Object;
    var oStringObject = new String;
    

    2、对象引用

    在 ECMAScript 中,不能访问对象的物理表示,只能访问对象的引用。每次创建对象,存储在变量中的都是该对象的引用,而不是对象本身。

    3、对象废除

    ECMAScript 拥有无用存储单元收集程序(garbage collection routine),意味着不必专门销毁对象来释放内存。
    把对象的所有引用都设置为 null,可以强制性地废除对象。例如:

    var oObject = new Object;
    // do something with the object here
    oObject = null;
    

    旧的浏览器(如 IE/MAC)没有全面的无用存储单元收集程序,所以在卸载页面时,对象可能不能被正确销毁。废除对象和它的所有特性是确保内存使用正确的最好方法。

    4、早绑定和晚绑定

    所谓绑定(binding),即把对象的接口与对象实例结合在一起的方法。

    早绑定(early binding)是指在实例化对象之前定义它的属性和方法,这样编译器或解释程序就能够提前转换机器代码。在 Java 和 Visual Basic 这样的语言中,有了早绑定,就可以在开发环境中使用 IntelliSense(即给开发者提供对象中属性和方法列表的功能)。ECMAScript 不是强类型语言,所以不支持早绑定。

    晚绑定(late binding)指的是编译器或解释程序在运行前,不知道对象的类型。使用晚绑定,无需检查对象的类型,只需检查对象是否支持属性和方法即可。ECMAScript 中的所有变量都采用晚绑定方法。这样就允许执行大量的对象操作,而无任何惩罚。

    三、ECMAScript 对象类型


    在 ECMAScript 中,所有对象并非同等创建的。
    一般来说,可以创建并使用的对象有三种:本地对象、内置对象和宿主对象。

    1、本地对象

    ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。它们包括:

    • Object
    • Function
    • Array
    • String
    • Boolean
    • Number
    • Date
    • RegExp
    • Error
    • EvalError
    • RangeError
    • ReferenceError
    • SyntaxError
    • TypeError
    • URIError

    2、内置对象

    • 定义:
      由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。

    这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262 只定义了两个内置对象,即 GlobalMath (它们也是本地对象,根据定义,每个内置对象都是本地对象)。

    3、宿主对象

    所有非本地对象都是宿主对象(host object),即由 ECMAScript 实现的宿主环境提供的对象。
    所有 BOM 和 DOM 对象都是宿主对象。

    四、ECMAScript 对象作用域


    作用域指的是变量的适用范围。

    1、公用、私有和受保护作用域

    • 概念
      在传统的面向对象程序设计中,主要关注于公用和私有作用域。公用作用域中的对象属性可以从对象外部访问,即开发者创建对象的实例后,就可使用它的公用属性。而私有作用域中的属性只能在对象内部访问,即对于外部世界来说,这些属性并不存在。这意味着如果类定义了私有属性和方法,则它的子类也不能访问这些属性和方法。

      受保护作用域也是用于定义私有的属性和方法,只是这些属性和方法还能被其子类访问。

    2、ECMAScript 只有公用作用域

    因为 ECMAScript 中只存在一种作用域 - 公用作用域。ECMAScript 中的所有对象的所有属性和方法都是公用的。所有属性和方法默认都是公用的!

    3、ECMAScript 没有静态作用域

    严格来说,ECMAScript 并没有静态作用域。不过,它可以给构造函数提供属性和方法。还记得吗,构造函数只是函数。函数是对象,对象可以有属性和方法。例如:

    function sayHello() {
      alert("hello");
    }
    
    sayHello.alternate = function() {
      alert("hi");
    }
    
    sayHello();     //输出 "hello"
    sayHello.alternate();   //输出 "hi"
    

    3、关键字 this

    • this 的功能
      在 ECMAScript 中,要掌握的最重要的概念之一是关键字 this 的用法,它用在对象的方法中。关键字 this 总是指向调用该方法的对象,例如:
    var oCar = new Object;
    oCar.color = "red";
    oCar.showColor = function() {
      alert(this.color);
    };
    
    oCar.showColor();       //输出 "red"
    

    五、ECMAScript 定义类或对象

    1、原始的方式

    因为对象的属性可以在对象创建后动态定义,所有许多开发者都在 JavaScript 最初引入时编写类似下面的代码:

    var oCar = new Object;
    oCar.color = "blue";
    oCar.doors = 4;
    oCar.mpg = 25;
    oCar.showColor = function() {
      alert(this.color);
    };
    
    

    这里有一个问题,就是可能需要创建多个 car 的实例。

    2、解决方案:工厂方式

    要解决该问题,开发者创造了能创建并返回特定类型的对象的工厂函数(factory function)。

    例如,函数 createCar() 可用于封装前面列出的创建 car 对象的操作:

    function createCar() {
      var oTempCar = new Object;
      oTempCar.color = "blue";
      oTempCar.doors = 4;
      oTempCar.mpg = 25;
      oTempCar.showColor = function() {
        alert(this.color);
      };
      return oTempCar;
    }
    
    var oCar1 = createCar();
    var oCar2 = createCar();
    
    

    通过这种方法,我们可以很容易地创建 car 对象的两个版本(oCar1 和 oCar2),它们的属性完全一样。

    3、为函数传递参数

    我们还可以修改 createCar() 函数,给它传递各个属性的默认值,而不是简单地赋予属性默认值:

    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",3,25);
    
    oCar1.showColor();      //输出 "red"
    oCar2.showColor();      //输出 "blue"
    

    给 createCar() 函数加上参数,即可为要创建的 car 对象的 color、doors 和 mpg 属性赋值。这使两个对象具有相同的属性,却有不同的属性值。

    4、构造函数方式

    创建构造函数就像创建工厂函数一样容易。第一步选择类名,即构造函数的名字。根据惯例,这个名字的首字母大写,以使它与首字母通常是小写的变量名分开。除了这点不同,构造函数看起来很像工厂函数。请考虑下面的例子:

    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",3,25);
    
    

    5、原型方式

    该方式利用了对象的 prototype 属性,可以把它看成创建新对象所依赖的原型。

    这里,首先用空构造函数来设置类名。然后所有的属性和方法都被直接赋予 prototype 属性。我们重写了前面的例子,代码如下:

    function Car() {
    }
    
    Car.prototype.color = "blue";
    Car.prototype.doors = 4;
    Car.prototype.mpg = 25;
    Car.prototype.showColor = function() {
      alert(this.color);
    };
    
    var oCar1 = new Car();
    var oCar2 = new Car();
    

    5、原型方式的问题

    构造函数没有参数。使用原型方式,不能通过给构造函数传递参数来初始化属性的值。

    6、混合的构造函数/原型方式

    联合使用构造函数和原型方式,就可像用其他程序设计语言一样创建对象。这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。结果是,所有函数都只创建一次,而每个对象都具有自己的对象属性实例。

    我们重写了前面的例子,代码如下:

    function Car(sColor,iDoors,iMpg) {
      this.color = sColor;
      this.doors = iDoors;
      this.mpg = iMpg;
      this.drivers = new Array("Mike","John");
    }
    
    Car.prototype.showColor = function() {
      alert(this.color);
    };
    
    var oCar1 = new Car("red",4,23);
    var oCar2 = new Car("blue",3,25);
    
    oCar1.drivers.push("Bill");
    
    alert(oCar1.drivers);   //输出 "Mike,John,Bill"
    alert(oCar2.drivers);   //输出 "Mike,John"
    

    参考资料


    【1.ECMAScript 面向对象】http://www.w3school.com.cn/js/pro_js_object_oriented.asp

    相关文章

      网友评论

          本文标题:ECMAScript 面向对象

          本文链接:https://www.haomeiwen.com/subject/gvkbwxtx.html