JS: The Definitive Guide 笔记 - Object
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()