JS: The Definitive Guide 笔记 - Object

JavaScript里最基本的数据类型是对象。
JavaScript里的对象其实是一个无序的属性集合,属性又是一个个的名-值对。
 
除了字符串,数字,true,false,null或者undefined以外,其他所有的值在JavaScript里头都是对象。
 
对象是引用类型,如果变量x表示一个对象,当执行var y = x;语句后,实际上y和x指向的是同一个对象。所以,当你通过y改变对象的值,这种变化也会反映到x上。
 
 
如何创建对象:
1. 字面量表示法:
var book = {};   //创建一个没有属性的对象
var book = {
   name : "The Definitive Guide",
   "main title" : "JavaScript",      //当属性名中间有空格,或者“-”时,要用引号把属性名括起来
   author : {                          //对象的属性也可以是对象
      firstname : "Rex",
      lastname : "Mai
   }
};    

2. 使用new关键字:

var o = new Object(); // 创建一个空对象,效果等同{}.
var a = new Array(); // 创建一个空数组,效果等同 [].
var d = new Date(); // 创建一个表示当前时间的对象
var r = new RegExp("js"); // 创建一个正则表达式对象

3. 使用Object.create() ,这是ECMAScript5 新添加的方法,该方法接受一个参数——对象原型。

var o1 = Object.create({x:1, y:2});
var o2 = Object.create(Object.prototype); // 结果等同于{}或new Object()

你可以给该方法传null,结果会是一个不继承任何属性和方法的空对象

获取对象的值

通过.或者[]操作符。

book.title;
book["title"];

var propertyName = "title";
book[propertyName];

如果对象的属性是固定的,那么这两个方法的作用差别不大。但由于javascript是一种松散类型的语言,所以,你可以在程序运行期间为对象添加任意数量的属性。当你使用.操作符访问对象属性时,.后面的名字其实只是一个标识符,所以你必须完整的输入这个标识符,才能够访问到。

属性特性:

在ECMAScript5中,添加了API同获取和设置属性特性。在这里,我们有一个对象,property descriptor,它用来表示属性的4个特性(value/get, writable/set, enumerable, configurable)。其中,writable, enumerable和configurable属性为布尔值,get和set属性为function。

我们可以通过Object.getOwnPropertyDescriptor()获取特定对象里某个属性的property descriptor,这个方法只能获取对象的自有属性。

// Returns {value: 1, writable:true, enumerable:true, configurable:true}
Object.getOwnPropertyDescriptor({x:1}, "x");
// Now query the octet property of the random object defined above. // Returns { get: /*func*/, set:undefined, enumerable:true, configurable:true} Object.getOwnPropertyDescriptor(random, "octet");
// Returns undefined for inherited properties and properties that don't exist. Object.getOwnPropertyDescriptor({}, "x"); // undefined, no such prop Object.getOwnPropertyDescriptor({}, "toString"); // undefined, inherited

通过Object.defineProperty()来设置属性特性,该方法有3个参数,1.操作的对象,2.要修改或创建的属性名,3.property descriptor对象

var o = {}; // Start with no properties at all
// Add a nonenumerable data property x with value 1.
Object.defineProperty(o, "x", { value : 1,
                    writable: true,
                    enumerable: false,
                    configurable: true});
// Check that the property is there but is nonenumerable
o.x; // => 1
Object.keys(o) // => []
// Now modify the property x so that it is read-only
Object.defineProperty(o, "x", { writable: false });

传入的property descriptor对象不需要把4个特性全部包含进去;如果是创建新属性,特性又没有出现在property descriptor对象里,则那些特性值为false或者undefined。如果是修改属性,没出现的特性值不会改变。该方法只会创建或修改自有对象,不会改变改变继承的属性。

应该也注意到了,Object.defineProperty()只能创建或设置一个属性,如果想一次性创建或修改多个属性,可以使用Object.defineProperties(),它有2个参数,1.要修改的对象,2.包含属性名及property descriptor对象的对象

var p = Object.defineProperties({}, {
  x: { value: 1, writable: true, enumerable:true, configurable:true },
  y: { value: 1, writable: true, enumerable:true, configurable:true },
  r: {
  get: function() { return Math.sqrt(this.x*this.x + this.y*this.y) },
     enumerable:true,
     configurable:true
}
});

 

对象属性:

原型属性(prototype):对象的原型属性石用来继承属性的。

通过直接量创建的对象,原型为:Object.prototype
通过new创建的对象,原型为:构造函数的prototype
通过Object.create()创建的对象,原型为:使用的第一个参数

ECMAScript5中,将对象作为参数传入Object.getPrototypeOf(),可以获取对象的原型。

通过对象直接量或Object.create()创建的对象包含一个名为constructor的属性,该属性指代Object()构造函数。

想要检测一个对象是否是另一个对象的原型(或出于原型链中),可以使用isPrototypeOf()方法。

p.isPrototypeOf(o)         //若o是p的原型或存在于原型链中,则返回true

类属性(class):对象的类属性是一个字符串,用以表示对象类型信息。ECMAScript3和5都没有提供设置这个属性的方法,而且只有一个间接的方法可以查询它——默认的toString()方法。但由于很多对象继承的toString()方法被重写了,所以最好使用call去调用。

function classof(o) {             //该函数可以返回传递给它的任意对象的类
  if( o === "null" ) return "Null";
  if( o === "undefined") return "Undefined";
  Object.prototype.toString.call(o).slice(8,-1);
} 

 内置构造函数创建的对象包含“类属性”,它与构造函数名称相匹配。通过对象直接量,Object.create()和自定义构造函数创建的对象的类属性是“Object”,创建的对象也是一样,类属性也是“Object”。因此对于自定义的类来说,没办法通过类属性来区分对象的类。

classof(null) // => "Null"
classof(1) // => "Number"
classof("") // => "String"
classof(false) // => "Boolean"
classof({}) // => "Object"
classof([]) // => "Array"
classof(/./) // => "Regexp"
classof(new Date()) // => "Date"
classof(window) // => "Window" (a client-side host object)
function f() {}; // Define a custom constructor
classof(new f()); // => "Object"

可扩展属性(extensible):该属性用以表示是否可以给一个对象添加新属性。在ECMAScript5中,所有内置对象和自定义对象都是显示可扩展。

Object.esExtensible():用来判断对象是否是可扩展的。
Object.preventExtensions():用来将对象转换为不可扩展。注意,一旦将对象设为不可扩展,则无法再将其转换回可扩展。该方法也只会影响到对象本身的可扩展性。如果给一个不可扩展的对象的原型添加属性,这个不可扩展对象还是会继承这些新属性。
Object.seal():和preventExtensions()类似,它除了可以将对象设备不可扩展外,还可以将对象的所有自有属性设置为不可配置的。也就是说,不可以给这个对象添加新属性,而且它的已有属性也不能删除或者配置,但是它的已有可写属性依然可以设置。被封闭(seal)的对象,是不能解锁(unseal)的。我们可以通过Object.isSeal()方法来检测对象是否封闭。
Object.freeze():更严格的锁定对象。和seal类似,不过它还会将自有的所有数据属性设为只读(如果对象的存储器有setter方法,该属性不会被影响,也就是说可以通过给属性赋值调用它们)。通过Object.isFrozen()检测对象是否冻结。

对象方法:

toString(),toLocaleString(),toJSON(),valueOf()

posted @ 2012-12-14 21:42  Rex.M  阅读(946)  评论(0编辑  收藏  举报