JavaScript面向对象程序设计

一、对象

JavaScript的简单数据类型包括数字、字符串、布尔值、null值和undefined值。其他所有的值都是对象。数字、字符串和布尔值“貌似”对象,因为它们拥有方法,但它们是不可变的。JavaScript中的对象是可变的键控集合(Keyed collections)。在JavaScript中,数组时对象,函数是对象,正在表达式是对象,当然,对象自然也是对象。

对象是属性的集合,每一个属性具有一个名称和一个值。数学的名字可以是包括空字符串在内的任意字符串。属性值可以是除undefined值之外的任何值。

JavaScript里的对象是无类型的(class-free)。它对新属性的名字和值是没有限制的。对象适合用于汇集和管理数据。对象可以保护其他对象,所以它们可以很容易的表示成树状或图形结构。

1、创建(Create)

可以采用两种方法来实例化对象。

第一种方法是使用new关键字
var myObject = new Object();

new 关键字调用构造函数,或者更通用的说法是构造器。构造器将初始化新创建的对象。下面的代码演示了一个名为Zombie(僵尸)对象的构造器,构造器初始化该对象的name属性,然后使用new关键字实例化一个Zombie对象。this关键字用于引用当前对象,不能对它进行赋值,但可以将this关键字的值赋给另外一个变量

//构造函数
function Zombie( name ) {
    this.name = name;
}
var smallZombie = new Zombie( "Booger");
使用对象字面量创建对象

另外一种实例化新对象的方法更加方便:使用对象字面量,这种方式创建的对象更像其他语言中的散列(hash)或关联数组。

var myObject = { };
var webSite= {
    "url": "www.mybry.com",
    "siteName": "读你"
};

在属性列表的最后一项值的末尾,请不要使用结尾逗号。不同的浏览器对此的解析并不一致

2、检索(Retrieval)

既可以使用方括号来访问对象的属性,也可以使用点操作符来访问。下面的代码示例了者两种方式:

webSite['url'];
//"www.mybry.com"
webSite.siteName;
//"读你"

采用方括号方式访问属性时,可以使用JavaScript的关键字作为属性名,但不推荐这样做,使用点操作符方式访问属性时则不能使用。使用点操作符方式,代码更加简短。JSLint鼓励开发人员使用点操作符方式。因为属性也可以是对象,可以在任意层次上嵌套对象。

下面假设有一个父亲father对象,他有自己的名字name和年龄age,他有两个儿子childrenOne和childrenTwo,两个孩子当然也是对象,也有名字name个年龄age,然后我们访问孩子childrenOne的名字:

var father = {
  'name': 'zhangsan',
  'age': 50,
  'childrenOne': {
    'name': 'zhangsi',
    'age': 22
  },
  'childrenTwo': {
    'name': 'zhangwu',
    'age': 12
  }
};
console.log(father.childrenOne.name);
//输出:zhangsi

JavaScript是一种动态的语言,因此更新一个属性只需要重新对属性赋值即可。要从对象中移除一个属性,只需要使用delete操作符。删除一个不存在的属性并不会造成任何危险。要遍历对象的所有属性,可以使用for…in循环,比如下面的代码块:

var obj1 = {
  'properties1': 1,
  'properties2': 2
};
var i;
for( i in obj1 ){
  console.log( i );
}
//properties1
//properties2
3、原型(Prototype)

JavaScript使用原型继承(prototype inheritance),对象直接从其他对象继承,从而创建新的对象。简而言之,对象继承了另外一个对象的属性。JavaScript中没有类,这是与Java和C#等语言相比一个较大的差别。原型就是其他对象的模型(model)。

每个对象都连接到一个原型对象,并且它可以从中继承属性。所有通过对象字面量创建的对象都连接到Object.prototype,它是JavaScript中的标配对象。

当创建一个新对象时,可以选择某个对象作为它的原型。JavaScript提供的实现机制杂乱而复杂,但其实可以被明显地简化。我们将给Object对象增加一个create方法。这个方法创建一个使用原型对象作为其原型的新对象。

if (typeof Object.beget !== 'function') {
  Object.create = function (o) {
    var F = function () { };
    F.prototype = o;
    return new F();
  };
}
var another = Object.create( webSite );
console.log(another);

在firebug中输出如下结果,正是一个对象。

原型连接在更新时是不起作用的。当我们对某个对象做出改变时,不会触及该对象的原型,原型连接只有在检索值的时候才会被用到。如果我们尝试去获取对象的某个属性值,但该对象没有此属性名,那么JavaScript会试着从原型对象中获取属性值。如果那个原型对象也没有该属性,那么再从他的原型中寻找,以此类推,直到该过程最后到达终点Object.prototype。如果想要的属性完全不存在与原型链中,那么结果就是undefined值。这个过程称为委托。

原型关系是一种动态关系。如果我们添加一个新的属性到原型中,该属性会立即对所有基于该原型创建的对象可见。

4.引用(Reference)

引用是一个指向对象实例位置的指针。Object是引用类型,由于所有对象都是通过引用传递的,,它们永远不会被复制:

var x = myObject;
x.nickname = '这世间唯有梦想和好姑娘不可辜负~~~';
var nick = myObject.nickname;
//因为x和stooge是指向同一个对象的引用,所以nick为‘zhangsan’
console.log(nick); //这世间唯有梦想和好姑娘不可辜负~~~
//因为a、b和c每个都引用一个不同的空对象
var a = { }, b = { }, c = { };
//a、b和c都引用同一个空对象
a = b = c = { };

修改绑定于一个原型的属性,将修改基于该原型的所有其他对对象的原型。

对象是自知的,或者说对象知道自己的属性。要检查某个属性是否存在,可以使用hasOwnProperty()方法,该方法将返回一个布尔值。

5、减少全局变量污染

很多程序员认为,应该避免使用全局变量。有一些办法可以避免扰乱全局名称空间,一种办法是使用单个全局变量作为顶层对象,包含程序或框架中的所有方法和属性。按照惯例,名称空间的字母全部大写,但值得注意的是常量通常也大写格式。

ZOMBIE_GENERATOR = {};
ZOMBIE_GENERATOR.Zombies = {
    smallZombie : 'Booger',

    largeZombie : 'Bruce'

}

采用上面的代码定义名称空间之后,Zombies就不会与全局名称空间中的任何其他变量冲突。另外一种减少冲突的方式是使用闭包。

6、反射(Reflection)

检查对象并确定对象有什么属性时很容易的事情,只要试着去检索该属性并验证取得值。typeof操作符对确定属性的类型很有帮助:

typeof father.name;                      // 'string'
typeof father.age;                         // 'number'
typeof father.childrenOne;         // 'object'
typeof father.xxx;                         // 'undefined'

请注意原型链中任何属性都会产生值:

typeof father.toString;            // 'function'
typeof father.constructor;      // 'function'

有两种方法去处理掉这些不需要的属性。第一个是让你的程序做检查并丢弃掉值为函数的属性。一般来说,当你想让对象在运行时动态获取自身信息时,你关注更多的时数据,而你应该意识到一些值可能是函数。

另一个方法时使用hasOwnProperty方法,如果对象拥有独有的属性,它会返回true。hasOwnProperty方法不会检查原型链。

father.hasOwnProperty('name');                // true
father.hasOwnProperty('constructor');     // false

7、枚举(Enumeraton)

for...in语句可以用来遍历一个对象中的所有属性名。该枚举过程将会列出所有的属性——包括函数和你可能不关心的原型中的属性——所以有必要过滤那些你不想要的值。最为常用的过滤时hasOwnPropery方法,一级使用typeof来排除函数。

属性名出现的顺序是不确定的,因此要对任何可能出现的顺序有所准备。如果你想要确保属性以特定的顺序出现,最好的办法就是完全避免使用for in语句,而是创建一个数组,在其中以正确的顺序包含属性名:

var properties = [
  'first-name',
  'middle-name',
  'last-name',
  'profession'
];
for(var i = 0; i < properties.length; i++){
  console.info(properties[i]);
}

通过使用for而不是for in,可以得到我们想要的属性,而不必担心可能发掘出的原型链中的属性,并且我们按正确的顺序取得了它们的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值