在ECMAScript中,Object是一个特殊的对象。它本身是一个顶级对象,同时还是一个构造函数,可以通过它(如:new Object())来创建一个对象。我们可以认为JavaScript中所有的对象都是Object的一个实例。
1. Object类型与对象的定义
对象是一个包含键/值对的集合。ECMAScript提供了两种创建创建对象的方式:构造函数创建和字面量创建。构造函数创建是指使用new Object()的方式创建,而字面量创建是指使用{}创建。示例如下:
// 使用构造函数创建对象
var obj = new Object({key:'a value'});
// 使用构造函数创建对象后,再添加属性
var obj1 = new Object();
obj1.key = 'a value';
// 使用字面量创建
var obj2 = {
key: 'a value'
};
// 字面量也可以使用以下形式
var obj3 = {};
obj3.key = 'a value';
使用构造函数创建对象时,如果不需要传递还可以省略括号:
var obj = new Object;
从以上几种形式可以看出,使用字面量的形式创建对象更为简洁,这也是比较推荐的一种使用方式。
2. Object类型的属性和方法
在面向对象编程中,属性和方法有两种:类方法(属性)和实例方法(属性)。类方法一般是指静态方法,是只能通过类名调用的方法,如:Object.key()。而实例方法是只能在实例化后,通过实例名调用的方法,如:obj.valueOf()。虽然Object并不是严格意义上的类,但它也有这两种方法/属性,Object的实例方法可以被继承,可以其实例及子对象的实例中调用;而其类方法,只能通过Object来调用。
2.1 实例属性与方法
ECMAScript基于原型链-prototype实现对象的继承,我们所说实例属性/方法就是指定prototype上的属性/方法。而Object是所有对象的父对象,它的实例属性与方法也同时存在于所有的对象的实例中。
Object的实例属性/方法如下:
Object.prototype.constructor- 对象的构造函数。前面使用new创建对象时,其构造函数是Object()Object.prototype.hasOwnProperty(propName)- 返回一个布尔值。用于检查给定的属性是实例属性,而非从原型链继承的属性。var o = new Object(); o.site = 'niefengjun.cn'; o.hasOwnProperty('site'); // 返回 true o.hasOwnProperty('toString'); // 返回 false,toString继承自ObjectObject.prototype.isPrototypeOf(object)- 返回一个布尔值。用于检查给定的对象是否在原型链上Object.prototype.propertyIsEnumerable(propName)- 判断对象属性是否是可枚举的Object.prototype.toLocaleString()- 返回对象的字符串表示,即:调用Object.prototype.toString()Object.prototype.toString()- 返回对象的字符串表示Object.prototype.valueOf()- 返回对象的原始值
2.2 类属性与方法
Object中有几个类方法,这些方法可实现对象继承、属性添加/修改等,在JavaScript编程中这些属性/方法会经常使用,通过这些方法可以实现类似Java等高级语言中的一些面向对象特征。
Object.assign()-复制多个对象属性到新对象
Object.assign()方法可以把任意多个的源对象自身的可枚举属性(enumerable=true)拷贝给目标对象,然后返回目标对象。
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
详细介绍请参考:JavaScript 对象属性拷贝
Object.create()-通过对象原型创建新对象
Object.create()方法用于通过对象原型来创建新对象,这样我们就可以通过个方法来实现的JavaScript对象的继承。
详细介绍请参考:Object.create()方法实现对象继承与创建新的JavaScript对象
Object.defineProperty()-为对象添加或修改属性
Object.defineProperty()用于为对象添加一个属性或修改已存在的属性。
详细介绍请参考:Object.defineProperty()定义/修改属性
Object.defineProperties()-添加或修改多个对象属性
Object.defineProperties()是Object.defineProperty()方法的批量操作。
详细介绍请参考:Object.defineProperties()定义/修改多个属性
Object.freeze() - 冻结对象
Object.freeze()用于冻结对象,是将对象设置为不能添加新属性、不能修改已有属性的值、不能删除已有属性,且不能修改已有属性的可枚举性、可配置性、可写性。
var obj = {
prop: function (){},
foo: "bar"
};
// 对象冻结前,可以添加新的属性,也可以修改或删除已有属性
obj.foo = "baz";
obj.lumpy = "woof";
delete obj.prop;
var o = Object.freeze(obj);
assert(Object.isFrozen(obj) === true); // true
// 冻结后所有修改操作都会失败
obj.foo = "quux"; // 静默失败
obj.site = "http://niefengjun.cn"; // 静默失败,并没有成功添加上新的属性
// 而在严格模式中,以上操作会抛出TypeError异常
Object.getOwnPropertyDescriptor() - 返回对象属性描述
该方法用于返回对象自有属性的描述,属性描述包括:configurable、enumerable、writable、value、get、set。自有属性指那些不是从原型链上继承的属性。
Object.getOwnPropertyDescriptor(obj, prop)
如,可以下面这样返回对象属性描述:
var o, d;
o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d is { configurable: true, enumerable: true, get: /*访问器函数*/, set: undefined }
o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// d is { configurable: true, enumerable: true, value: 42, writable: true }
o = {};
Object.defineProperty(o, "baz", { value: 8675309, writable: false, enumerable: false });
d = Object.getOwnPropertyDescriptor(o, "baz");
// d is { value: 8675309, writable: false, enumerable: false, configurable: false }
Object.getOwnPropertyNames() - 返回对象自身的所有属性名
返回对象自身的所有属性名组成的数组,包括不可枚举属性。
Object.getOwnPropertyNames(obj)
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]
Object.getPrototypeOf() - 返回对象的原型属性
返回对象的原型属性,即从原型链继承的属性
Object.getPrototypeOf(object)
使用示例:
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
Object.is() - 返回两个值是否严格相等
这个方法是ECMAScript 2015中新增的方法,两个值是否严格相等,其与===操作符类似。示例如下:
Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
var test = { a: 1 };
Object.is(test, test); // true
Object.is(null, null); // true
// 两个特例,=== 也没法判断的情况
Object.is(0, -0); // false
Object.is(NaN, 0/0); // true
Object.isExtensible() - 判断对象是否是可扩展的
Object.isExtensible()用于判断对象是否是可扩展的,即:是否可向其添加新属性。
// 新对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty); // === true
// ...可以变的不可扩展.
Object.preventExtensions(empty);
Object.isExtensible(empty); // === false
// 密封对象是不可扩展的.
var sealed = Object.seal({});
Object.isExtensible(sealed); // === false
// 冻结对象也是不可扩展.
var frozen = Object.freeze({});
Object.isExtensible(frozen); // === false
Object.isFrozen() - 判断对象是否已冻结
判断对象是否已冻结,使用Object.freeze()冻结对象后,该方法将返回true
// 一个对象默认是可扩展的,所以它也是非冻结的.
assert(Object.isFrozen({}) === false);
// 一个不可扩展的空对象同时也是一个冻结对象.
var vacuouslyFrozen = Object.preventExtensions({});
assert(Object.isFrozen(vacuouslyFrozen) === true);
// 一个非空对象默认也是非冻结的.
var oneProp = { p: 42 };
assert(Object.isFrozen(oneProp) === false);
Object.isSealed() - 判断对象是否已密封
判断对象是否已密封,使用Object.seal()密封对象后,该方法将返回true,密封对象不能删除属性
// 新建的对象默认不是密封的.
var empty = {};
Object.isSealed(empty); // === false
// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(empty);
Object.isSealed(empty); // === true
Object.keys() - 返回对象所有可遍历的属性名
该方法会返回一个数组,其中包含对象的所有可遍历属性的名称
var arr = ["a", "b", "c"];
alert(Object.keys(arr)); // 弹出"0,1,2"
// 类数组对象
var obj = { 0 : "a", 1 : "b", 2 : "c"};
alert(Object.keys(obj)); // 弹出"0,1,2"
// getFoo是个不可枚举的属性
var my_obj = Object.create({}, { getFoo : { value : function () { return this.foo } } });
my_obj.foo = 1;
alert(Object.keys(my_obj)); // 只弹出foo
Object.preventExtensions() - 阻止对象扩展
该方法用于设置对象不可扩展,设置后Object.isExtensible()将返回false
Object.seal() - 密封对象
在防止对象属性被删除时我们可以使用Object.seal()方法将对象密封
Object.setPrototypeOf() - 设置对象原型
这个方法是ECMAScript 2015(ES6)规范中新增的方法,用于设置对象的原型
Object.setPrototypeOf(obj, prototype)
