Object常用方法总结
# 属性获取/遍历/设置
# in
所有属性:
自身 + 原型链 + 可枚举 + 不可枚举 + 符号 + 非符号
let symbol = Symbol('c')
let obj = let obj = Object.create(
{
a: 1,
},
{
b: {
value: 2,
enumerable: false,
},
[symbol]: {
value: 3,
enumerable: true
},
d: {
value: 4
}
}
)
'a' in obj // true
'b' in obj // true
symbol in obj // true
'd' in obj // true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# for...in
遍历
自身 + 原型链 + 可枚举 + 非符号
属性
let obj = Object.create(
{
a: 1,
},
{
b: {
value: 2,
enumerable: false,
},
c: {
value: 2,
enumerable: true,
},
[Symbol('c')]: {
value: 3,
enumerable: true,
},
}
)
for (let key in obj) {
// c
// a
console.log(key)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Object.keys
返回
自身 + 可枚举 + 非符号
属性的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致
- 在 ES5 里,如果此方法的参数不是对象(而是一个原始值),那么它会抛出 TypeError
- ES6 后会自动装箱
// a 是原型上的属性
// getFoo 是不可枚举的
var myObj = Object.create(
{
a: 1,
},
{
getFoo: {
value: function () {
return this.foo
},
},
}
)
// foo 是可枚举且定义在自身的属性
myObj.foo = 1
// 符号属性
myObj[Symbol('bar')] = 2
console.log(Object.keys(myObj)) // ['foo']
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Reflect.ownKeys
返回
自身 + 可枚举 + 不可枚举 + 符号 + 非符号
属性
Reflect.ownKeys
= Object.getOwnPropertySymbols
+ Object.getOwnPropertyNames
let symbol = Symbol('c')
let obj = Object.create(
{
a: 1,
},
{
b: {
value: 2,
enumerable: true,
},
[symbol]: {
value: 3,
},
d: {
value: 4,
},
}
)
Reflect.ownKeys(obj) // ['b', 'd', Symbol(c)]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Object.getOwnPropertyNames
返回一个由指定对象的所有
自身 + 可枚举 + 不可枚举 + 非符号
属性的属性名组成的数组
let my_obj = Object.create(
{
a: 1,
},
{
getFoo: {
value: function () {
return this.foo
},
},
[Symbol('c')]: {
value: 2,
enumerable: true,
},
}
)
my_obj.foo = 1
console.log(Object.getOwnPropertyNames(my_obj)) // ["getFoo", "foo"]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Object.getOwnPropertySymbols
返回一个由指定对象的所有
自身 + 可枚举 + 不可枚举 + 符号
属性的属性名组成的数组
let my_obj = Object.create(
{
a: 1,
},
{
getFoo: {
value: function () {
return this.foo
},
enumerable: false,
},
[Symbol('c')]: {
value: 2,
enumerable: true,
},
}
)
my_obj.foo = 1
console.log(Object.getOwnPropertyNames(my_obj).sort()) // ["foo", "getFoo"]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Object.prototype.hasOwnProperty
返回一个布尔值,指示对象属性中是否具有指定的
自身 + 可枚举 + 不可枚举 + 符号 + 非符号
属性(也就是,是否有指定的键)
let s = Symbol('s')
let obj = Object.create(
{
a: 1,
},
{
b: {
value: 2,
},
c: {
value: 3,
enumberable: true,
},
[s]: {
value: 4,
},
}
)
obj.hasOwnProperty('a') // false
obj.hasOwnProperty('b') // true
obj.hasOwnProperty('c') // true
obj.hasOwnProperty(s) // true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Object.getOwnPropertyDescriptor
获取对象上
自有属性
对应的属性描述符对象,属性不存在则返回undefined
let s = Symbol('s')
let obj = Object.create(
{
a: 1,
},
{
[s]: {
value: 4,
},
}
)
// {"value":4, "writable":false, "enumerable":false, "configurable":false}
Object.getOwnPropertyDescriptor(obj, s)
// {
// b: {value: 2, writable: false, enumerable: false, configurable: false},
// c: {value: 3, writable: false, enumerable: false, configurable: false},
// Symbol(s): {value: 4, writable: false, enumerable: false, configurable: false}
// }
Object.getOwnPropertyDescriptors(obj)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Object.entries
返回一个给定对象
自身 + 可枚举
属性的键值对
数组
const object1 = {
a: 'somestring',
b: 42,
}
for (const [key, value] of Object.entries(object1)) {
console.log(`${key}: ${value}`)
}
// expected output:
// "a: somestring"
// "b: 42"
2
3
4
5
6
7
8
9
10
11
12
# Object.values
返回一个给定对象
自身 + 可枚举
的属性的值
的数组
var my_obj = Object.create(
{},
{
getFoo: {
value: function () {
return this.foo
},
},
}
)
my_obj.foo = 'bar'
console.log(Object.values(my_obj)) // ['bar']
2
3
4
5
6
7
8
9
10
11
12
# Object.defineProperty
直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并
返回此对象
一次性设置多个属性使用Object.defineProperties
# 属性描述符对象
value/writable
不能和 存取描述符
同时存在
let val = 1
Object.defineProperty(obj, 'a', {
value: val,
set(v) {
val = v
},
})
// TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
2
3
4
5
6
7
8
# 数据描述符
- value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
默认为 undefined
。 - writable
当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变,
默认为 false
。 - enumberable
当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。
默认为 false
。 - configable
当且仅当该属性的 configurable 键值为 true 时,该属性的
描述符才能够被改变
,同时该属性才能被 delete 删除
。默认为 false
。
# 存取描述符
get
属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时
不传入任何参数
,但是会传入 this 对象
(由于继承关系,这里的this并不一定是定义该属性的对象
)。该函数的返回值会被用作属性的值。默认为 undefined
。set
属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是
被赋予的新值
),会传入赋值时的 this 对象
。默认为 undefined
# 原型相关
# Object.create
创建一个新对象,使用现有的对象来提供新创建的对象的
__proto__
该方法的第二个参数
的属性类型参照 Object.defineProperties
的第二个参数。
- 用于继承
// Shape - 父类(superclass)
function Shape() {
this.x = 0
this.y = 0
}
// 父类的方法
Shape.prototype.move = function (x, y) {
this.x += x
this.y += y
console.info('Shape moved.')
}
// Rectangle - 子类(subclass)
function Rectangle() {
Shape.call(this) // call super constructor.
}
// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype, {
constructor: {
value: Rectangle,
},
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- 结合 Object.assing 可以用来实现继承多个对象,通常称为
混入
function MyClass() {
SuperClass.call(this)
OtherSuperClass.call(this)
}
// 继承一个类
MyClass.prototype = Object.create(SuperClass.prototype)
// 混合其它
Object.assign(MyClass.prototype, OtherSuperClass.prototype)
// 重新指定constructor
MyClass.prototype.constructor = MyClass
2
3
4
5
6
7
8
9
10
11
# Objet.getPrototypeOf
获取一个对象的原型(
内部[[Prototype]]属性的值
)
let f = function () {}
Object.getPrototypeOf(f) === f.prototype // false
Object.getPrototypeOf(f) === f.__proto__ // true
2
3
4
# Object.setPrototypeOf
设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null
let f = function () {}
Object.setPrototypeOf(f, {
name: 'f',
})
console.log(f.__proto__) // { name: 'f' }
2
3
4
5
6
# Object.prototype.isPrototypeOf
用于测试一个对象是否存在于另一个对象的原型链上
- 与 instanceof 运算符不同,
o instanceof Ctor
检测的是构造器 Ctor 的 prototype
属性是否出现在对象 o 的原型链
(即__proto__
) 中的任何位置
let A = function () {}
let a = new A()
a instanceof A // true
A.isPrototypeOf(a) // false
A.prototype.isPrototypeOf(a) // true
2
3
4
5
6
7
8
9
# 其他
# Object.assign
用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。
Object.assign(target, ...sources)
- 只会拷贝源对象自身的并且可枚举的属性到目标对象,继承的和不可枚举的属性不会拷贝
- Symbol 类型的属性都会被拷贝
- 无法拷贝属性的特性们
let s1 = {
// 自身可枚举属性
a: 1,
// symbol属性
[Symbol('b')]: 2,
}
// 不可枚举属性
Object.defineProperty(s1, 'c', {
value: 3,
enumerable: false,
})
// 继承属性
Object.setPrototypeOf(s1, {
d: 4,
})
let t = Object.assign({}, s1)
// {
// a: 1,
// Symbol(b): 2
// }
console.log(t)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- source 对象值为 null 或 undefined 的时候不会抛出错误,但是会被忽略
- target 对象的值为 null 或 undefined 则会报错
let t = Object.assign({}, undefined, null, {
a: undefined,
b: null,
})
// {
// a: undefined,
// b: null
// }
console.log(t)
2
3
4
5
6
7
8
9
- 对于引用类型的属性,拷贝的是引用,而不是值,浅拷贝
let o1 = {
a: {
b: {
c: 123,
d: 123,
},
},
}
let o2 = {
a: {
b: {
e: 123,
},
},
}
let t = Object.assign({}, o1, o2)
// {
// a: {
// b: {
// e: 123,
// }
// }
// }
console.log(t)
t.a.b = 234
console.log(o2.a.b) // 234
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Object.is
判断两个值是否为同一个值,不会进行类型转换
- 与
===
运算符不同的是,Object.is 认为+0
与-0
不相等NaN
与NaN
相等
Object.is = function (x, y) {
// SameValue algorithm
if (x === y) {
// +0 != -0
return x !== 0 || 1 / x === 1 / y
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y
}
}
2
3
4
5
6
7
8
9
10
# Object.freeze
冻结一个对象。返回传递的对象,而不是创建一个被冻结的副本
判断一个对象是否被冻结使用 Object.isFrozen()
一个被冻结的对象再也不能被修改;
- 不能向这个对象添加新的属性,
- 不能删除已有属性,
- 不能修改该对象已有属性的可枚举性、可配置性、可写性,
- 不能修改已有属性的值
- 该对象的原型也不能被修改
- 浅冻结 而不是 深冻结
obj1 = {
internal: {},
}
Object.freeze(obj1)
obj1.internal.a = 'aValue'
obj1.internal.a // 'aValue'
2
3
4
5
6
7
8
# Object.seal
封闭一个对象,阻止添加新属性并将所有现有属性标记为
不可配置
。当前属性的值只要原来是可写的就可以改变
- 密封一个对象会让这个对象变的
不能添加新属性
,且所有已有属性会变的不可配置
- 属性不可配置的效果就是属性变的
不可删除
,以及不能修改其属性描述符对象,除了 value 属性 - 属性的值仍然可以修改
判断一个对象是否被密封 Object.isSealed()
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
Object.defineProperty(obj, 'foo', {
value: 'the friendly duck',
})
obj.foo // 'the friendly duck'
// 删除属性将会失败
delete obj.foo
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34