创建对象两种方式:
let o = new Object();
let b = {}; // 字面量(推荐)
对象构造器可以接受任何类型的参数,并且会自动识别参数类型,选择合适的构造器来完成对象创建:
let o = new Object('something');
o.constructor; // ƒ String() { [native code] }
let n = new Object(123);
n.constructor; // ƒ Number() { [native code] }
Object构造器的成员
Object.prototype
Object的原型对象,是所有对象的原型(包括Object对象本身),JavaScript中其他对象正是通过该属性上添加属性来实现继承关系。
let s = new String('xq');
Object.prototype.custom = 1;
console.log(s.custom); // 1
Object.prototype(原型对象)的成员
Object.prototype.constructor
该属性指向用来构造该对象的构造器,在这里为Object()
;实例对象constructor
指向构造函数。
Object.prototype.constructor === Object; // true
var o = new Object();
o.constructor === Object; // true
Object.prototype.toString(radix)
该方法返回一个用户描述目标对象的字符串,PS,当目标对象是一个Number
对象时候,可以传递一个用于进制数的参数radix
,该参数默认值为10.
var o = { prop:1 };
o.toString(); // '[object Object]'
var n = new Number(255);
n.toString(); // '255'
n.toString(16); // 'ff'
Object.prototype.toLocaleString()
该方法的作用与toString()
基本相同,只不过它做一些本地化处理。该方法会根据当前对象的不同而被重写,例如Date()
,Number()
,Array()
,它们的值都会以本地化的形式输出。当然,对于包括Object()
在内的其他大多数对象来说,该方法与toString()
是基本相同的。 在浏览器环境下,可以通过BOM
对象Navigator
的language
属性(在IE
中则是userLanguage
)来了解当前所使用的语言:
navigator.language; //'en-US'
Object.prototype.valueOf()
该方法返回用基本类型所表示指定对象的原始值。如果对象没有原始值,则valueOf
将返回对象本身。如果Number
对象返回的是它的基本数值,而Date
对象返回的是时间戳。如果无法用基本数据类型表示,该方法会放回this
本身。
对象 | 返回值 |
---|---|
Array | 返回数组对象本身。 |
Boolean | 布尔值。 |
Date | 存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC-时间戳。 |
Function | 函数本身。 |
Number | 数字值。 |
Object | 对象本身。这是默认情况。 |
String | 字符串值。 |
Math 和 Error 对象没有 valueOf 方法。 |
Object.prototype.hasOwnProperty(prop)
该方法仅在目标属性为对象自身属性时返回true
,而当该属性是从原型链中继承而来或根本不存在时,返回false
。返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)
const o = { prop:1 };
o.hasOwnProperty('prop'); // true
o.hasOwnProperty('toString'); // false
o.hasOwnProperty('formString'); // false
Object.prototype.isPrototypeOf(obj)
返回布尔值,用于测试一个对象是否存在于另一个对象的原型链上。
const s = new String('');
Object.prototype.isPrototypeOf(s); // true
String.prototype.isPrototypeOf(s); // true
Array.prototype.isPrototypeOf(s); // false
在ES5
中附加的Object
属性
ES5中引入了属性描述符的概念,属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。
数据描述符包括:
value
:该属性对应的值。可以是任意有效地JavaScript
的值,默认为undefined
。writable
:当且仅当该属性的writable
键值为true
时,属性的值,也就是value
,才能被赋值运算符修改,默认值为false
。configurable
:当且仅当该属性的configurable
键值为true
时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false
。enumerable
:当且仅当该属性的enumerable
键值为true
时,该属性才会出现在对象的枚举属性中。默认为false
。
存取描述符包括:
get
:属性的getter
函数,如果没有getter
,则为undefined
。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入this
对象(由于继承关系,这里的this
并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。默认为undefined
。set
:属性的setter
函数,如果没有setter
,则为undefined
。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的this
对象。默认为undefined
。 ```javascript const person = {}; Object.defineProperty(person, ‘legs’, { value: 2, writable: true, configurable: true, enumerable: true });
const person = {}; Object.defineProperty(person, ‘legs’, { set:function(v) { return this.value = v; }, get: function(v) { return this.value; }, configurable: true, enumerable: true });
**数据描述符**(其中属性为:`enumerable`,`configurable`,`value`,`writable`)与**存取描述符**(其中属性为`enumerable`,`configurable`,`set()`,`get()`)之间是有互斥关系的。在定义了`set()`和`get()`之后,描述符会认为存取操作已被 定义了,其中再定义`value`和`writable`会**引起错误**。
<a name="object-defineproperty-obj-prop-descriptor-es5"></a>
### Object.defineProperty(obj, prop, descriptor) (ES5)
会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
```javascript
const object1 = {};
Object.defineProperty(object1, 'property1', {
value: 42,
writable: false
});
object1.property1 = 77;
// throws an error in strict mode
console.log(object1.property1);
// expected output: 42
Object.defineProperties(obj, props) (ES5)
该方法的作用与defineProperty()
基本相同,只不过它可以用来一次定义多个属性。 比如:
const glass = Object.defineProperties({}, {
'color': {
value: 'transparent',
writable: true
},
'fullness': {
value: 'half',
writable: false
}
});
glass.fullness; // 'half'
Object.getPrototypeOf(obj) (ES5)
之前在ES3
中,我们往往需要通过Object.prototype.isPrototypeOf()
去猜测某个给定的对象的原型是什么,如今在ES5
中,我们可以直接询问改对象。你的原型对象(xxx.prototype
)是什么?
Object.getPrototypeOf([]) === Array.prototype; // true
Object.getPrototypeOf(Array.prototype) === Object.prototype; // true
Object.getPrototypeOf(Object.prototype) === null; // true
Object.create(obj, descr) (ES5)
该方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
。
返回值:一个新对象,并为其设置原型对象。带着指定的原型对象和属性。
const parent = { hi: 'Hello' };
const o = Object.create(parent, {
prop: {
value: 1
}
});
o.hi; // 'Hello'
// 获得它的原型
Object.getPrototypeOf(parent) === Object.prototype;
// true 说明parent的原型对象是Object.prototype
Object.getPrototypeOf(o);
// {hi: "Hello"} // 说明o的原型对象是{hi: "Hello"}
o.hasOwnProperty('hi');
// false 说明hi是原型对象上的
o.hasOwnProperty('prop');
// true 说明prop是自身上的属性。
Object.freeze(obj) (ES5)
Object.freeze()
方法可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。
const deadline = Object.freeze({date: 'yesterday'});
Object.keys(obj)
该方法是一种特殊的fot-in循环,只返回当前对象的属性,而这些属性也必须输可枚举的。返回值是一个字符串数组。
const o = { own: 202 };
Object.keys(o); // ['own']
在ES6中附加的Object属性
Object.is(value1, value2)
该方法用来比较两个值是否严格相等。它与严格比较运算符(===
)的行为基本一致。 不同之处只有两个:一是+0
不等于-0
,而是NaN
等于自身。
Object.is('xq', 'xq'); // true
Object.is({},{}); // false
Object.is(+0, -0); // false
+0 === -0; // true
Object.is(NaN, NaN); // true
NaN === NaN; // false
Object.assign(target, …sources) (ES6)
该方法用来源对象(source
)的所有可枚举的属性复制到目标对象(target
)。它至少需要两个对象作为参数,第一个参数是目标对象target
,后面的参数都是源对象(source
)。只有一个参数不是对象,就会抛出TypeError
错误。
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
obj = Object.assign(target, source1, source2);
target; // { a:1,b:2,c:3 }
obj; // { a:1,b:2,c:3 }
target === obj; // true
// 如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
const source3 = { a:2,b:3,c:4 };
Object.assign(target, source3);
target; // { a:2,b:3,c:4 }