zoukankan      html  css  js  c++  java
  • 【ECMAScript5】对象

    对象的创建和销毁都在 JavaScript 执行过程中发生。把对象的所有引用都设置为 null,可以强制性地废除对象。

    在 ECMAScript 中,所有对象并非同等创建的。

    一、对象类型

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

    1. 本地对象

    本地对象就是 ECMA-262 定义的类(引用类型)。它们包括:

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

    2. 内置对象

    ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。

    3. 宿主对象

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

    所有 BOM 和 DOM 对象都是宿主对象。

    二、对象作用域

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

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

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

    • ECMAScript 只有公用作用域
    • 建议性的解决方法:开发者确定了一个规约,在属性前后加下划线,告诉其他开发者,应该把该属性看作私有的。
    • ECMAScript 没有静态作用域

    1. 关键字this

    在 ECMAScript 中,要掌握的最重要的概念之一是关键字 this 的用法,它用在对象的方法中。关键字 this 总是指向调用该方法的对象。

    var oCar = new Object;
    oCar.color = "red";
    oCar.showColor = function() {
      alert(this.color);
    };
    
    oCar.showColor();        //输出 "red"

    在上面的代码中,关键字 this 用在对象的 showColor() 方法中。在此环境中,this 等于 oCar。等同于:

    var oCar = new Object;
    oCar.color = "red";
    oCar.showColor = function() {
      alert(oCar.color);
    };
    
    oCar.showColor();        //输出 "red"

    使用this的原因:因为在实例化对象时,总是不能确定开发者会使用什么样的变量名。使用 this,即可在任何多个地方重用同一个函数。

    三、定义类或对象

    1. 原始方式

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

    缺点:如果需要多个,就要创建多个对象。

    2. 工厂方式

    为了解决多个对象的问题,可以创建一个返回对象的工厂方法。

    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();

    缺点:功能上解决了重复创建函数对象的问题;语义上,该函数不太像是对象的方法。

    3. 构造函数方式

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

    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);

    4. 原型方式

    该方式利用了对象的 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();

    我们再看下面这个例子:

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

    属性 drivers 是指向 Array 对象的指针,该数组中包含两个名字 "Mike" 和 "John"。由于 drivers 是引用值,Car 的两个实例都指向同一个数组。这意味着给 oCar1.drivers 添加值 "Bill",在 oCar2.drivers 中也能看到。输出这两个指针中的任何一个,结果都是显示字符串 "Mike,John,Bill"。

    5. 混合的构造函数/原型方式

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

    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"

    这种方式是 ECMAScript 采用的主要方式,它具有其他方式的特性,却没有他们的副作用。

    6. 动态原型方法

    动态原型方法的基本想法与混合的构造函数/原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。

    function Car(sColor,iDoors,iMpg) {
      this.color = sColor;
      this.doors = iDoors;
      this.mpg = iMpg;
      this.drivers = new Array("Mike","John");
      
      if (typeof Car._initialized == "undefined") { //标记位, 判断是否已给原型赋予了任何方法。该方法只创建并赋值一次
        Car.prototype.showColor = function() {
          alert(this.color);
        };
        
        Car._initialized = true;
    
      }
    }

    四、修改对象

    prototype 属性不仅可以定义构造函数的属性和方法,还可以为本地对象添加属性和方法。

    1. 创建新方法

    (1)通过已有的方法创建新方法

    可以用 prototype 属性为任何已有的类定义新方法,就像处理自己的类一样。

    Number.prototype.toHexString = function() {
      return this.toString(16);
    };

    关键字 this 指向 Number 的实例,因此可完全访问 Number 的所有方法。有了这段代码,可实现下面的操作:

    var iNum = 15;
    alert(iNum.toHexString());        //输出 "F"

    (2)重命名已有的方法

    为已有的方法命名更易懂的名称。

    例如,可以给 Array 类添加两个方法 enqueue() 和 dequeue(),只让它们反复调用已有的 push() 和 shift() 方法即可:

    Array.prototype.enqueue = function(vItem) {
      this.push(vItem);
    };
    
    Array.prototype.dequeue = function() {
      return this.shift();
    };

    (3)添加与已有方法无关的方法

    Array.prototype.indexOf = function (vItem) {
      for (var i=0; i<this.length; i++) {
        if (vItem == this[i]) {
          return i;
        }
      }
    
      return -1;
    }

    (4)为本地添加新方法

    如果想给 ECMAScript 中每个本地对象添加新方法,必须在 Object 对象的 prototype 属性上定义它。所有本地对象都继承了 Object 对象,所以对 Object 对象做任何改变,都会反应在所有本地对象上。

    Object.prototype.showValue = function () {
      alert(this.valueOf());
    };
    
    var str = "hello";
    var iNum = 25;
    str.showValue();        //输出 "hello"
    iNum.showValue();        //输出 "25"

    2. 重定义已有的方法

    Function.prototype.toString = function() {
      return "Function code hidden";
    }
    function sayHi() {
      alert("hi");
    }
    
    alert(sayHi.toString());    //输出 "Function code hidden"
  • 相关阅读:
    【持续更新】GDB使用笔记
    PL/SQL Developer-官网下载地址
    kali 下程序卸载方法
    python2 安装scrapy出现错误提示解决办法~
    pyHook监听用户鼠标、键盘事件
    pip 安装pandas报UnicodeDecodeError: 'ascii' codec can't decode byte 0xd5错
    Python模块常用的几种安装方式
    解决Kali Linux没有声音
    关于破解路由器密码
    解决Python2.7的UnicodeEncodeError: ‘ascii’ codec can’t encode异常错误
  • 原文地址:https://www.cnblogs.com/myitnews/p/12187614.html
Copyright © 2011-2022 走看看