《JavaScript高级程序设计》摘要(二)

第三章 对象基础

这一章主要有五大要点:

  1. 对象引用
  2. 对象的类型
  3. 关键字this
  4. 定义类或对象
  5. 修改对象

下面为你一 一道来。

首先普及一下面向对象语言四种基本能力:

  1. 封装——把相关的信息(无论属性或方法)储存在对象中的能力。
  2. 聚集——把一个对象存储在另一个对象内的能力。
  3. 继承——由另一个类(或多个类)得来类的属性和方法的能力。
  4. 多态——编写能以多种方法运行的函数或方法的能力。

另外,对象的创建或销毁都在JavaScript执行过程中发生,理解这种范式的含义对理解整个语言至关重要。

3.1    对象引用

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

  • 对象废除 

    ECMAScript有无用存储单元收集程序,意味着不必专门销毁对象来释放内存。当再没有对象的引用时,称该对象被废除(dereference)了。

    每当函数执行完它的代码,无用存储单元收集程序都会运行,释放所有的局部变量。还有在一些其它不可预知的情况下,无用存储单元收集程序也会运行。

把对象的所有引用都设置为null,可以强制性的废除对象。例如:

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

每用完一个对象后,就将其废除来释放内存,这是个好习惯。

  • 早绑定和晚绑定

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

早绑定(early binding)是指在实例化对象之前定义它的属性和方法,像Java和Visual Basic都支持。但ECMAScript不是强类型语言,所以不支持早绑定。

晚绑定(late binding)指的是编译器或解释程序在运行前,不知道对象的类型。使用晚绑定,无需检查对象的类型,只需要检查对象是否支持属性和方法即可。

ECMAScript中的所有变量都采用晚绑定方法,这样就允许执行大量的对象操作,而无任何报错。

3.2    对象的类型

一般来说,可以创建并使用的对象有三种:

  1. 本地对象; 本地对象就是ECMA-262定义的类(引用类型)。它们包括:Object,Function,Array,String,Boolean,Number,Date,RegExp,Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError。
  2. 内置对象; ECMA-262之定义了两个内置对象,即Global和Math(它们也是本地对象),同时开发者不必明确实例化内置对象,它已被实例化了。
  3. 宿主对象; 所有非本地对象都是宿主对象。

3.3    关键字this

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

var car = new Object();
car.color = "red";
car.showColor = function(){
      alert(this.color);  //outputs "red"
   }

在此环境中,this等于car,即:

car.showColor = function(){
      alert(car.color);  //outputs "red"
}

注意,引用对象的属性时,必须使用this关键字。例如,如果采用如下的代码,则showColor()方法不会运行:

function showColor(){
     alert(color);
}

如果不用对象或this关键字引用变量,ECMAScript就会把它们看做局部变量或全局变量。然后该函数将查找名为color的局部或全局变量,但是不会找到的。

那结果如何,该函数将在警告中显示“null”。

3.4    定义类或对象

使用预定义对象的能力只是面向对象语言的能力的一部分,它真正的强大之处在于能够创建自己专用的类和对象。

与ECMAScript中的许多特性一样,可以用各种方法实现这一点。

  • 工厂方式; 

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

var car = new Object();
car.color = "red";
car.door = 4;
car.mpg = 23;
car.showColor = function(){
    alert(this.color);
};

最后一个属性实际上是指向函数的指针,意味着该属性是个方法。执行这段代码后,就可以使用对象car。问题是可能需要创建多个car实例。

要解决此问题,开发者创造了能创建并返回特定类型的对象的工厂函数。例如:

function createCar(){
    var car = new Object();
    car.color = "red";
    car.doors = 4;
    car.mpg = 23;
    car.showColor = function(){
        alert(this.color);
   };
   
   return car;
}
var car1 = createCar();
var car2 = createCar();

调用此函数时,将创建新对象,并赋予它们所有必要的属性,复制一个前面说明的car对象。当然,还可以修改createCar()函数,给它传递参数而不是赋予属性默认值。

另外,每个对象都共享了同一个函数。

  • 构造函数方式; 构造函数看起来很像工厂函数。如下面的例子:
    function Car(color, doors, mag){
        this.color = color;
        this.doors = doors;
        this.mpg = mpg;
        this.showColor = function(){
           alert(this.color);
       };
    }
    
    var car1 = new Car("red",4,33);
    var car2 = new Car("blue",2,133);

你可能注意到差别了,在构造函数内部无创建对象,而是使用this关键字。

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

重写前面的例子,代码如下所示:

function Car(){

}

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

var car1 = new Car();
var car2 = new Car();

首先定义构造函数(Car)无任何代码,接下来通过给Car的prototype属性添加属性去定义Car对象的属性。

从语义上讲,所有属性看起来都属于一个对象。此外,使用该方法,还能用instanceof运算符检查给定变量指向的对象的类型。

但遗憾的是,它并不尽如人意。

函数共享不会造成任何问题,但对象却是很少被多个实例共享的。当一个实例修改属性或方法时,其它对象的属性或方法也被同时修改。

那是否有种合理的创建对象的方法呢?答案是有,需要联合使用构造函数和原型方式。

  • 构造函数/原型方式; 

联合使用构造函数和原型方式,这种概念非常简单。即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。

结果所有函数都只创建一次,而每个对象都具有自己的对象属性实例。再重写前面的例子:

function Car(color, doors, mpg){
    this.color = color;
    this,doors = doors;
    this.mpg = mpg;
    this.drivers = new Array("Mike","Sue");
}

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

var car1 = new Car("red",4,33);
var car2 = new Car("red",2,133);

car1.drivers.push("Mark");

alert(car1.drivers);  //outputs "Mike,Sue,Mark"
alert(car2.drivers);  //outputs "Mike,Sue"

同时因为只创建showColor()函数的一个实例,所以没有内存浪费。

 

 

 

 

转载于:https://my.oschina.net/u/3415601/blog/877896

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值