方法列表
- assign
- create
- defineProperty
- defineProperties
- entries
- freeze
- getOwnPropertyDescriptor
- getOwnPropertyNames
- getOwnPropertySymbols
- getPrototyoeOf
- is
- isExtensible
- isFrozen
- isSealed
- keys
- preventExtensions
- seal
- setPrototypeOf
- values
assign
Object.assign
方法将所有可枚举(Object.propertyIsEnumerable()
返回 true)和自有(Object.hasOwnProperty()
返回 true)属性从一个或多个源对象复制到目标对象,返回修改后的对象
如果目标对象与源对象具有相同的 key,则目标对象中的属性将被源对象中的属性覆盖,后面的源对象的属性将类似地覆盖前面的源对象的属性
参数说明
assign (
target: object,
...source: object[],
) return target // 目标对象
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
target | 是 | object | 目标对象,接收源对象属性的对象,也是修改后的返回值 |
…source | 否 | object[] | 源对象,包含将被合并的属性 |
示例
复制对象与合并对象
// 复制对象
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
// 合并对象
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }
如果 source
的属性是一个引用值,则他只会复制其引用值
const target = {}
const source = { numbers: [1, 2, 3, 4, 5] }
Object.assign(target, source)
source.numbers.push(6)
console.log(target) // [1, 2, 3, 4, 5, 6]
console.log(source) // [1, 2, 3, 4, 5, 6]
原型链上的属性和不可枚举属性不能被复制
const obj = Object.create(
{}, // 这里是 obj 的 prototype
{
name: {
value: 'obj',
},
type: {
value: 'object',
enumerable: true,
},
},
)
const newObj = Object.assign({}, obj)
console.log(newObj) // { type: 'object' }
create
Object.create
方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)
参数说明
create (
proto: object | null
propertiesObject: object
) return object // 带着指定的原型对象及其属性
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
proto | 是 | object | null | 新创建对象的原型对象 |
propertiesObject | 否 | object | 如果该参数被指定且不为 undefined ,则该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。这些属性对应于 Object.defineProperties 的第二个参数 |
示例
正常的创建一个对象
const obj = Object.create(
Object.prototype,
{
name: {
value: 'obj',
writable: true,
enumerable: true,
configurable: true,
}
}
)
console.log(obj) // { name: 'obj' }
使用 null
作为 proto
创建对象
并不推荐这样使用,如果使用null作为原型,会产生许多问题
const normalObj = {};
const nullProtoObj = Object.create(null)
console.log("normalObj is: " + normalObj); // "normalObj is: [object Object]"
console.log("nullProtoObj is: " + nullProtoObj); // 报错 Cannot convert object to primitive value,因为没有继承到 Object.prototype.toString 方法
巧用
Object.create
可以使用在构造函数继承上
function Shape() {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};
function Rectangle() {
Shape.call(this);
}
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
const rect = new Rectangle();
console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
rect.move(1, 1); // 'Shape moved.'
defineProperty
Object.defineProperty
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
该方法允许精确地添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,在枚举对象属性时会被枚举到(for...in
或 Object.keys
方法),可以改变这些属性的值,也可以删除这些属性。这个方法允许修改默认的额外选项(或配置)。默认情况下,使用 Object.defineProperty
添加的属性值是不可修改(immutable)的
参数说明
defineProperty (
obj: object,
prop: string | Symbol,
descriptor: object // 属性描述符
) return object // 被传递给函数的对象
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 要定义属性的对象 |
prop | 是 | string | Symbol | 要定义或修改的属性的名称或 Symbol |
descriptor | 是 | object | 要定义或修改的属性描述符 |
prop 属性描述符
descriptor {
value: any, // 属性对应的值 默认为 undefined
writable: boolean, // 是否可写 默认为 false
enumerable: boolean, // 是否可枚举 默认为 false
configurable: boolean, // 是否可配置 默认为 false
get: function, // 访问此属性时调用的函数 默认为 undefined
set: function, // 设置此属性是调用的函数 默认为 undefined
}
get () return any
set (
value: any // 设置时传入的值
) return any
如果一个描述符不具有 value
、writable
、get
和 set
中的任意一个键,那么它将被认为是一个数据描述符。如果一个描述符同时拥有 value
或 writable
和 get
或 set
键,则会产生一个异常
也就是说 当 value
或 writable
存在时,不能同时设置 get
或 set
示例
创建一个常规对象 (可枚举,可配置,可写)
var o = {}; // 创建一个新对象
// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a",
{
value: 37,
writable: true,
enumerable: true,
configurable: true
}
);
console.log(o) // { a: 37 }
// 使用 get 和 set 写法
// 在对象中添加一个设置了存取描述符属性的示例
var bValue = 38;
Object.defineProperty(o, "b", {
// 使用了方法名称缩写(ES2015 特性)
// 下面两个缩写等价于:
get() { return bValue; },
set(newValue) { bValue = newValue; },
enumerable : true,
configurable : true
});
// 数据描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", {
value: 0x9f91102,
get() { return 0xdeadbeef; }
});
// 抛出错误 TypeError: value appears only in data descriptors, get appears only in accessor descriptors
创建一个不可写属性 writable: false
var o = {};
Object.defineProperty(o, "a",
{
value: 37,
writable: false,
enumerable: true,
configurable: true
}
);
o.a = 99
// 这里不会报错 但值也不会更改
console.log(o) // { a: 37 }
创建一个不可枚举属性 enumerable: false
var o = {}
// enumerable 的默认值是 false 这里为了更好区分所以手写一下
Object.defineProperty(o, 'a', { value: 1, enumerable: true })
Object.defineProperty(o, 'b', { value: 2, enumerable: false })
Object.defineProperty(o, 'c', { value: 3, enumerable: true })
for (const k in o) {
console.log(k, o[k])
/**
* 这里 2 并没有打印出来
* a 1
* c 3
*/
}
关于这点其实 chrome 的控制台可以非常容易的看到
不可枚举的属性颜色要比别的属性淡些
创建一个不可枚举属性 configurable: false
其实也可以简单理解成是 不可删除的
var o = {}
Object.defineProperty(o, 'a', { value: 1, configurable: true })
Object.defineProperty(o, 'b', { value: 2, configurable: false })
Object.defineProperty(o, 'c', { value: 3, configurable: true })
console.log(o) // { a: 1, b: 2, c: 3 }
delete o.a
delete o.b
delete o.c
console.log(o) // { b: 2 }
defineProperties
Object.defineProperties
方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象
Object.defineProperties
本质上定义了 obj
对象上 props
的可枚举属性相对应的所有属性
也可以理解成 Object.defineProperty
的批发版
参数说明
defineProperties (
obj: object,
props: object, // 就像是对象描述符的集合,键名对应属性名
) return object // 被传递给函数的对象
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 在其上定义或修改属性的对象 |
props | 是 | object | 要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅 Object.defineProperty ) |
示例
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
});
console.log(obj) // { property1: true, property2: 'Hello' }
entries
Object.entries
方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for in
循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)
Object.entries
返回一个数组,其元素是与直接在 object
上找到的可枚举属性键值对相对应的数组。属性的顺序与通过手动循环对象的属性值所给出的顺序相同
参数说明
entries (
obj: object
) return array // 自身可枚举属性的键值对数组
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 可以返回其可枚举属性的键值对的对象 |
示例
正常使用
const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
使用 for in
循环
// 使用 for in 循环
const obj = { a: 5, b: 7, c: 9 };
for (const [key, value] of Object.entries(obj)) {
console.log(`${key} ${value}`);
/**
* a 5
* b 7
* c 9
*/
}
同时 forEach
也可以使用
const obj = { a: 5, b: 7, c: 9 };
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`);
/**
* a 5
* b 7
* c 9
*/
});
freeze
Object.freeze
方法可以冻结一个对象,返回和传入的参数相同的对象,一个被冻结的对象具有以下特点
- 不能添加新的属性
- 不能删除已有的属性
- 不能修改已有属性的可枚举性、可配置性、可写性
- 不能修改已有属性的值
- 不能修改该对象的原型
参数说明
freeze (
obj: object
) return object // 被冻结之后的对象
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 要被冻结的对象 |
示例
冻结对象
在严格模式下给已冻结的对象进行增删改操作会报错
var obj = {
prop: function () { },
foo: 'bar'
};
// 新的属性会被添加,已存在的属性可能
// 会被修改或移除
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;
console.log(obj) // { foo: 'baz', lumpy: 'woof' }
// 作为参数传递的对象与返回的对象都被冻结
// 所以不必保存返回的对象(因为两个对象全等)
var o = Object.freeze(obj);
o === obj; // true
Object.isFrozen(obj); // true
// 现在任何改变都会失效
obj.foo = 'quux'; // 静默地不做任何事
// 静默地不添加此属性
obj.quaxxor = 'the friendly duck';
console.log(obj ) // { foo: 'baz', lumpy: 'woof' }
// 在严格模式,如此行为将抛出 TypeErrors
function fail() {
'use strict';
obj.foo = 'sparky'; // throws a TypeError
delete obj.quaxxor; // 返回 true,因为 quaxxor 属性从来未被添加
obj.sparky = 'arf'; // throws a TypeError
}
fail();
// 试图通过 Object.defineProperty 更改属性
// 下面两个语句都会抛出 TypeError.
Object.defineProperty(obj, 'ohai', { value: 17 });
Object.defineProperty(obj, 'foo', { value: 'eit' });
// 也不能更改原型
// 下面两个语句都会抛出 TypeError.
Object.setPrototypeOf(obj, { x: 20 })
obj.__proto__ = { x: 20 }
冻结数组
let a = [0];
Object.freeze(a); // 现在数组不能被修改了。
a[0] = 1; // 静默不做任何事
a.push(2); // 报错
// 在严格模式下会报错
function fail() {
"use strict"
a[0] = 1; // 报错
a.push(2); // 报错
}
fail();
巧用
深冻结
冻结数组并不是深冻结的,当一个数组里面的属性属于引用值时,这个属性的值并不能同时被冻结
obj = {
internal: {}
};
Object.freeze(obj);
obj.internal.a = 'aValue';
obj1.internal.a // 'aValue'
所以我们需要去实现一个深度冻结函数
// 深冻结函数。
function deepFreeze(obj) {
// 取回定义在 obj 上的属性名
var propNames = Object.getOwnPropertyNames(obj);
// 在冻结自身之前冻结属性
propNames.forEach(function(name) {
var prop = obj[name];
// 如果 prop 是个对象,冻结它
if (typeof prop == 'object' && prop !== null)
deepFreeze(prop);
});
// 冻结自身 (no-op if already frozen)
return Object.freeze(obj);
}
obj2 = {
internal: {}
};
deepFreeze(obj2);
obj2.internal.a = 'anotherValue';
obj2.internal.a; // undefined
getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor
方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
该方法允许对一个属性的描述进行检索。在 Javascript 中, 属性 由一个字符串类型的“名字”(name)和一个“属性描述符”(property descriptor)对象构成
参数说明
getOwnPropertyDescriptor (
obj: object,
prop: string,
) return object | undefiend // 如果存在则返回对象属性的描述符 反之返回 undefined
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 需要查找的目标对象 |
prop | 是 | string | 目标对象内属性名称 |
示例
var o, d;
o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
// configurable: true,
// enumerable: true,
// get: /*the getter function*/,
// set: undefined
// }
o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// d {
// 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 {
// value: 8675309,
// writable: false,
// enumerable: false,
// configurable: false
// }
getOwnPropertyNames
Object.getOwnPropertyNames
方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组
Object.getOwnPropertyNames
返回一个数组,该数组对元素是 obj
自身拥有的枚举或不可枚举属性名称字符串。 数组中枚举属性的顺序与通过 for in
循环(或 Object.keys
)迭代该对象属性时一致。数组中不可枚举属性的顺序未定义
参数说明
getOwnPropertyNames (
obj: object,
) return string // 在给定对象上找到的自身属性对应的字符串数组
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 一个对象,其自身的可枚举和不可枚举属性的名称被返回 |
示例
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"]
// 使用 Array.forEach 输出属性名和属性值
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
console.log(val + " -> " + obj[val]);
});
// 输出
// 0 -> a
// 1 -> b
// 2 -> c
// 不可枚举属性
var my_obj = Object.create({}, {
getFoo: {
value: function() { return this.foo; },
enumerable: false
}
});
my_obj.foo = 1;
console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]
此方法不会获取到 prototype
上的属性
function ParentClass() {}
ParentClass.prototype.inheritedMethod = function() {};
function ChildClass() {
this.prop = 5;
this.method = function() {};
}
ChildClass.prototype = new ParentClass;
ChildClass.prototype.prototypeMethod = function() {};
console.log(
Object.getOwnPropertyNames(
new ChildClass() // ["prop", "method"]
)
);
getOwnPropertySymbols
Object.getOwnPropertySymbols
方法返回一个给定对象自身的所有 Symbol
属性的数组
与 Object.getOwnPropertyNames
类似,您可以将给定对象的所有符号属性作为 Symbol 数组获取。 请注意,Object.getOwnPropertyNames
本身不包含对象的 Symbol 属性,只包含字符串属性。
因为所有的对象在初始化的时候不会包含任何的 Symbol,除非你在对象上赋值了 Symbol 否则 Object.getOwnPropertySymbols
只会返回一个空的数组。
一个很好的例子 Array
的迭代器就是一个 Symbol
但是打印 Array[Symbol.iterator]
的时候会显示 undefined
打印 [][Symbol.iterator]
则会出出现对应的函数
参数说明
getOwnPropertySymbols (
obj: object
) return array // 在给定对象自身上找到的所有 Symbol 属性的数组
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 要返回 Symbol 属性的对象 |
示例
var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");
obj[a] = "localSymbol";
obj[b] = "globalSymbol";
var objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols.length); // 2
console.log(objectSymbols) // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0]) // Symbol(a)
getPrototyoeOf
Object.getPrototypeOf
方法返回指定对象的原型(内部[[Prototype]]
属性的值)。
参数说明
getPrototypeOf (
obj: object
) return object | null // 给定对象的原型。如果没有继承属性,则返回 null
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 要返回其原型的对象 |
示例
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
var reg = /a/;
Object.getPrototypeOf(reg) === RegExp.prototype; // true
is
Object.is
方法判断两个值是否为同一个值
如果满足以下任意条件则两个值相等
- 都是
undefined
- 都是
null
- 都是
true
或都是false
- 都是相同长度、相同字符、按相同顺序排列的字符串
- 都是相同对象(意味着都是同一个对象的值引用)
- 都是数字且
- 都是
+0
- 都是
-0
- 都是
NaN
- 都是同一个值,非零且都不是
NaN
- 都是
参数说明
is (
value1: any,
value2: any,
) return boolean
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
value1 | 是 | any | 被比较的第一个值 |
value2 | 是 | any | 被比较的第二个值 |
示例
普通判断
Object.is(25, 25); // true
Object.is('foo', 'foo'); // true
Object.is('foo', 'bar'); // false
Object.is(null, null); // true
Object.is(undefined, undefined); // true
Object.is(window, window); // true
Object.is([], []); // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
// Case 3: NaN
Object.is(NaN, 0/0); // true
Object.is(NaN, Number.NaN) // true
+0
与 -0
当我们使用 全等(===
)时 +0
与 -0
是相等的
但是当我们使用 Object.is
时,他们是不相等的
可以说 Object.is
更为严格
Object.is(0, -0); // false
Object.is(+0, -0); // false
Object.is(-0, -0); // true
Object.is(0n, -0n); // true
也可以用来判断 NaN
Object.is(NaN, 0/0); // true
Object.is(NaN, Number.NaN) // true
isExtensible
Object.isExtensible
方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。
参数说明
isExtensible (
obj: object,
) return boolean
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 需要检测的对象 |
示例
// 新对象默认是可扩展的。
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
isFrozen
Object.isFrozen
方法判断一个对象是否被冻结
一个对象是冻结的是指它不可[扩展](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible)
,所有属性都是不可配置的,且所有数据属性(即没有 getter 或 setter 组件的访问器的属性)都是不可写的
使用方法同 isExtensible
这里不再赘述了
示例
// 一个对象默认是可扩展的,所以它也是非冻结的。
Object.isFrozen({}); // === false
// 一个不可扩展的空对象同时也是一个冻结对象。
var vacuouslyFrozen = Object.preventExtensions({});
Object.isFrozen(vacuouslyFrozen) //=== true;
// 一个非空对象默认也是非冻结的。
var oneProp = { p: 42 };
Object.isFrozen(oneProp) //=== false
// 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象,
// 因为 p 属性仍然是可以配置的 (而且可写的).
Object.preventExtensions(oneProp);
Object.isFrozen(oneProp) //=== false
// 此时,如果删除了这个属性,则它会成为一个冻结对象。
delete oneProp.p;
Object.isFrozen(oneProp) //=== true
// 一个不可扩展的对象,拥有一个不可写但可配置的属性,则它仍然是非冻结的。
var nonWritable = { e: "plep" };
Object.preventExtensions(nonWritable);
Object.defineProperty(nonWritable, "e", { writable: false }); // 变得不可写
Object.isFrozen(nonWritable) //=== false
// 把这个属性改为不可配置,会让这个对象成为冻结对象。
Object.defineProperty(nonWritable, "e", { configurable: false }); // 变得不可配置
Object.isFrozen(nonWritable) //=== true
// 一个不可扩展的对象,拥有一个不可配置但可写的属性,则它仍然是非冻结的。
var nonConfigurable = { release: "the kraken!" };
Object.preventExtensions(nonConfigurable);
Object.defineProperty(nonConfigurable, "release", { configurable: false });
Object.isFrozen(nonConfigurable) //=== false
// 把这个属性改为不可写,会让这个对象成为冻结对象。
Object.defineProperty(nonConfigurable, "release", { writable: false });
Object.isFrozen(nonConfigurable) //=== true
// 一个不可扩展的对象,值拥有一个访问器属性,则它仍然是非冻结的。
var accessor = { get food() { return "yum"; } };
Object.preventExtensions(accessor);
Object.isFrozen(accessor) //=== false
// ...但把这个属性改为不可配置,会让这个对象成为冻结对象。
Object.defineProperty(accessor, "food", { configurable: false });
Object.isFrozen(accessor) //=== true
// 使用 Object.freeze 是冻结一个对象最方便的方法。
var frozen = { 1: 81 };
Object.isFrozen(frozen) //=== false
Object.freeze(frozen);
Object.isFrozen(frozen) //=== true
// 一个冻结对象也是一个密封对象。
Object.isSealed(frozen) //=== true
// 当然,更是一个不可扩展的对象。
Object.isExtensible(frozen) //=== false
isSealed
Object.isSealed
方法判断一个对象是否被密封
如果这个对象是密封的,则返回 true
,否则返回 false
。密封对象是指那些不可 扩展
的,且所有自身属性都不可配置且因此不可删除(但不一定是不可写)的对象。
示例
// 新建的对象默认不是密封的。
var empty = {};
Object.isSealed(empty); // === false
// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象。
Object.preventExtensions(empty);
Object.isSealed(empty); // === true
// 但如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的。
var hasProp = { fee: "fie foe fum" };
Object.preventExtensions(hasProp);
Object.isSealed(hasProp); // === false
// 如果把这个属性变的不可配置,则这个属性也就成了密封对象。
Object.defineProperty(hasProp, 'fee', {
configurable: false
});
Object.isSealed(hasProp); // === true
// 最简单的方法来生成一个密封对象,当然是使用 Object.seal.
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed); // === true
// 一个密封对象同时也是不可扩展的。
Object.isExtensible(sealed); // === false
// 一个密封对象也可以是一个冻结对象,但不是必须的。
Object.isFrozen(sealed); // === true ,所有的属性都是不可写的
var s2 = Object.seal({ p: 3 });
Object.isFrozen(s2); // === false, 属性"p"可写
var s3 = Object.seal({ get p() { return 0; } });
Object.isFrozen(s3); // === true ,访问器属性不考虑可写不可写,只考虑是否可配置
keys
Object.keys
方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致。
Object.keys
返回一个所有元素为字符串的数组,其元素来自于从给定的 object
上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致。
参数说明
keys (
obj: object,
) return array
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 要返回其枚举自身属性的对象 |
示例
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // ['0', '1', '2']
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // ['0', '1', '2']
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // ['2', '7', '100']
var myObj = Object.create({}, {
getFoo: {
value: function () { return this.foo; }
}
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // ['foo']
preventExtensions
Object.preventExtensions
方法让一个对象变的不可扩展,也就是永远不能再添加新的属性
仅阻止添加自身的属性。但其对象类型的原型依然可以添加新的属性
参数说明
preventExtensions (
obj: object
) return object // 已经不可扩展的对象
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 将要变得不可扩展的对象 |
示例
// Object.preventExtensions 将原对象变的不可扩展,并且返回原对象。
var obj = {};
var obj2 = Object.preventExtensions(obj);
obj === obj2; // true
// 字面量方式定义的对象默认是可扩展的。
var empty = {};
Object.isExtensible(empty) // true
// ...但可以改变。
Object.preventExtensions(empty);
Object.isExtensible(empty) // false
// 使用 Object.defineProperty 方法为一个不可扩展的对象添加新属性会抛出异常。
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // 抛出 TypeError 异常
// 在严格模式中,为一个不可扩展对象的新属性赋值会抛出 TypeError 异常。
function fail()
{
"use strict";
nonExtensible.newProperty = "FAIL"; // throws a TypeError
}
fail();
seal
Object.seal
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变
通常,一个对象是可扩展的(可以添加新的属性)。密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。但属性的值仍然可以修改。尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出 TypeError
(在严格模式 中最常见的,但不唯一)。
参数说明
seal (
obj: object
) return object // 被密封的对象
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 将要被密封的对象 |
示例
var obj = {
prop: function() {},
foo: 'bar'
};
// 可以添加新的属性
// 可以更改或删除现有的属性
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;
var o = Object.seal(obj);
o === obj; // true
Object.isSealed(obj); // === true
// 仍然可以修改密封对象的属性值
obj.foo = 'quux';
// 但是你不能将属性重新定义成为访问器属性
// 反之亦然
Object.defineProperty(obj, 'foo', {
get: function() { return 'g'; }
}); // throws a TypeError
// 除了属性值以外的任何变化,都会失败。
obj.quaxxor = 'the friendly duck';
// 添加属性将会失败
delete obj.foo;
// 删除属性将会失败
// 在严格模式下,这样的尝试将会抛出错误
function fail() {
'use strict';
delete obj.foo; // throws a TypeError
obj.sparky = 'arf'; // throws a TypeError
}
fail();
// 通过 Object.defineProperty 添加属性将会报错
Object.defineProperty(obj, 'ohai', {
value: 17
}); // throws a TypeError
Object.defineProperty(obj, 'foo', {
value: 'eit'
}); // 通过 Object.defineProperty 修改属性值
setPrototypeOf
Object.setPrototypeOf
方法设置一个指定的对象的原型 ( 即,内部 [[Prototype]] 属性)到另一个对象或 null
。
参数说明
setPrototypeOf (
obj: object,
prototype: object | null,
) return undefined
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 要设置其原型的对象 |
prototype | 是 | object | 该对象的新原型 |
示例
var dict = Object.setPrototypeOf({}, null);
console.log(dict.__proto__) // undefined
var dict = Object.setPrototypeOf({}, { a: 1, b: 2, c: 3, });
console.log(dict.__proto__) // { a: 1, b: 2, c: 3 }
values
Object.values
方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用 for in
循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
参数说明
setPrototypeOf (
obj: object
) return array // 一个包含对象自身的所有可枚举属性值的数组
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
obj | 是 | object | 被返回可枚举属性值的对象 |
示例
var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']
var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = 'bar';
console.log(Object.values(my_obj)); // ['bar']
console.log(Object.values('foo')); // ['f', 'o', 'o']