静态方法

对象操作

Object.create()

语法:
  Object.create(proto, [propertiesObject])

作用:
  创建一个新对象,且新对象的原型为 proto

参数:

  • proto:新创建对象的原型对象;如果 proto 参数不是 null 或非原始包装对象,则抛出 TypeError 异常
  • propertiesObject:可选参数。如果该参数不为 undefined,则该对象的自有可枚举属性将为新创建的对象添加指定的属性值和对象的属性描述符 -> 例子

返回值:
  一个新对象,且该对象的原型指向 proto

原对象是否改变:
  否。(因为这是生成对象的方法,并没有原对象)

Object.assign()

语法:
  Object.assign(target, source)

作用:
  用于将所有可枚举属性的值从一个或多个源对象分配到目标对象

参数:

  • target:目标对象
  • source:源对象

返回值:
  目标对象

目标对象是否改变:
  是

补充:

  • 如果目标对象和源对象有相同的键,则源对象的值会覆盖目标对象的值。后面的源对象的值将类似地覆盖前面源对象的值
  • 此方法为浅拷贝,即 基本类型的值会拷贝,引用类型的值只是拷贝引用地址

Object.entries()

语法:
  Ojbect.entries(obj)

作用
  返回一个给定对象自身可枚举属性的键值对数组

参数
  obj:要返回其可枚举属性的键值对的对象

返回值
  传入参数的可枚举属性的键值对数组

原对象是否改变:
  否

例子

1
2
3
4
5
6
7
8
9
10
const obj = {
a:1,
b:2,
c:3
}
console.log(Object.entries(obj)) //-> [['a',1],['b',2],['c',3]]

const obj2 = Object.create(obj)
obj2.d = 4
console.log(Object.entries(obj2)); //-> [['d',4]]

Object.fromEntries()

语法:
  Object.fromEntries(entries)

作用:
  把键值对列表转换为一个对象(与 Object.entries() 是互逆的操作)

参数:
  entries:类似 ArrayMap 或者其他实现了可迭代协议的可迭代对象

返回值:
  由迭代对象条目提供对应属性的新对象

例子

1
2
3
4
5
6
7
const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
const obj = Object.fromEntries(map);
console.log(obj); // { foo: "bar", baz: 42 }

const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ];
const obj = Object.fromEntries(arr);
console.log(obj); // { 0: "a", 1: "b", 2: "c" }

Object.is()

语法:
  Object.is(value1, value2)

作用:
  判断两个值是否为同一个值

描述:
Object.is()在进行相等判断时,不会强制转换两边的值

如果满足以下任意条件,则两个值相等:

  • 都是 undefined
  • 都是 null
  • 都是 true 或 false
  • 都是相同长度、相同字符、按相同顺序排列的字符串
  • 都是相同对象(即都是同一个对象的值引用)
  • 都是数字,且:
    • 都是 +0
    • 都是 -0
    • 都是 NaN
    • 都是同一个值,非零且都不是 NaN

参数:

  • value1:被比较的第一个值
  • value2:被比较的第二个值

返回值:
  true 或 false

原对象是否改变:
  否

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

Object.is(0, -0); // false
Object.is(+0, -0); // false
Object.is(-0, -0); // true
Object.is(0n, -0n); // true

Object.is(NaN, 0/0); // true
Object.is(NaN, Number.NaN) // true

属性相关

Object.defineProperty()

语法:
  Ojbect.defineProperty(obj, prop, descriptor)

作用:
  在一个对象上定义新的属性或修改现有属性

参数

  • obj:要定义属性的对象
  • prop:要定义或修改的属性的名称
  • descriptor:要定义或修改属性的描述符,同 definedProperties描述符具有以下键:

返回值:
  被传递给函数的对象

原对象是否改变:
  是(只是改变的对应的键的属性或值)

例子:

1
2
3
4
5
6
7
const obj = {}
const returnValue = Object.defineProperty(obj,'name',{
value: 'John',
writable: true
})
console.log(obj) //=> { name: "John" }
console.log(returnValue) //=> { name: "John" }

Object.defineProperties()

语法:
  Ojbect.defineProperties(obj, props)

作用:
  在一个对象上定义新的属性或修改现有属性

参数

  • obj:定义或修改属性的对象
  • props:要定义其可枚举属性或修改的属性描述符的对象
    • 描述符具有以下键:
      • configurable
        • 说明:该属性描述符所在键的其他属性是否可以被修改
        • 默认值:false
      • enumerable
        • 说明:是否可枚举
        • 默认值:false
      • value
        • 说明:与属性关联的值
        • 默认值:undefined
      • writable
        • 说明:该属性对应的键的值能否被修改
        • 默认值:false
      • get
        • 说明:getter函数,函数返回值将被用作属性的值
        • 默认值:undefined
      • set
        • 说明:setter函数,函数仅接受参数赋值给该属性的新值
        • 默认值:undefined

返回值:
  传递给函数的对象

原对象是否改变:
  是(只是改变的对应的键的属性或值)

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const obj = {}
const returnValue = Object.defineProperties(obj, {
_name: {
value: 'ghosie',
configurable: true,
writable: true,
enumerable: false
},
name: {
enumerable: true,
get() {
return this._name
},
set(newValue) {
this._name = newValue
}
}
})

Object.keys(obj) //=> ['name']
console.log(returnValue) //=> { _name: 'ghosie', name: 'ghosie' }

Object.getOwnPropertyDescriptor()

语法:
  Object.getOwnPropertyDescriptor(obj, key)

作用:
  返回指定对象上的一个自有属性对应的属性描述符(自有属性,即直接赋予该对象的属性,不需要从原型链上进行查找的属性)

参数:

  • obj:要查找的目标对象
  • key:属性名称

返回值:
  如果指定的属性名称存在于对象上,则返回其属性描述符,否则返回 undefined

原对象是否改变:
  否

例子:

1
2
3
4
5
6
7
8
9
10
11
const obj = {a:1,b:2}
const r1 = Object.getOwnPropertyDescriptor(obj,'a')
const r2 = Object.getOwnPropertyDescriptor(obj,'c')

console.log(r1) //-> {
configurable: true,
enumerable: true,
value: 1,
writable: true
}
console.log(r2) //-> undefined

Object.getOwnPropertyDescriptors()

语法:
  Object.getOwnPropertyDescriptors(obj)

作用:
  获取一个对象的所有自身属性的属性描述符(自有属性,即直接赋予该对象的属性,不需要从原型链上进行查找的属性)

参数:
  obj:要查找的目标对象

返回值:
  一个对象,包含了目标对象的所有自身属性的描述符;如果没有任何自身属性,返回空对象

原对象是否改变:
  否

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const obj = {a: 1}
const r1 = Object.getOwnPropertyDescriptors(obj)

console.log(r1) // {a: {
configurable: true,
enumerable: true,
value: 1,
writable: true
}
}

const obj2 = {a:1, b:2}
const newObj = Object.create(
Object.getPrototypeOf(obj2),
Object.getOwnPropertyDescriptors(obj2)
)
console.log(newObj) //-> {a:1,b:2}
newObj.a = 3
console.log(obj2.a) // -> 1

Object.getOwnPropertyNames()

语法:
  Object.getOwnPropertyNames(obj)

作用:
  返回一个由 指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性) 组成的数组

参数:
  obj:一个对象

返回值:
  在给定对象上找到的自身属性对应的字符串数组

原对象是否改变:
  否

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const arr = ['a','b','c']
console.log(Object.getOwnPropertyNames(arr)) //-> ['0','1','2','length']

const objPro = { a: 1, b: 2 }
const obj = Object.create(objPro, {
c: {
enumerable: false,
value: 3
},
d: {
enumerable: true,
value: 4
},
[Symbol()]: {
enumerable: true,
value: 5
}
})
console.log(Object.getOwnPropertyNames(obj)) //-> ['c','d']

Object.getOwnPropertySymbols()

语法:
  Object.getOwnPropertySymbols(obj)

作用:
  返回一个由给定对象自身的所有 Symbol 属性组成的数组

参数:
  obj:一个对象

返回值:
  在给定对象上找到的所有 Symbol 属性组成的数组

原对象是否改变:
  否

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const objPro = { a: 1, b: 2 }
console.log(Object.getOwnPropertySymbols(objPro)) //-> []

const obj = Object.create(objPro, {
c: {
enumerable: false,
value: 3
},
d: {
enumerable: true,
value: 4
},
[Symbol(1)]: {
enumerable: false,
value: 5
},
[Symbol(2)]: {
enumerable: true,
value: 5
}
})
console.log(Object.getOwnPropertySymbols(obj)) //-> [Symbol(1),Symbol(2)]
console.log(typeof Object.getOwnPropertySymbols(obj)[0]) //-> Symbol

对象冻结、密封、扩展

Object.freeze()

语法:
  Object.freeze(obj)

作用:
  冻结一个对象(浅冻结),对象被冻结后,不能进行增删改操作(包括对象已有属性的可枚举性、可配置性),对象的原型也不能被修改

参数:
  obj:要冻结的对象

返回值:
  被冻结的对象

原对象是否改变:
  是

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
const obj = {a:1,b:2,c:{d:3},e:[1,2,3]}
const objFreeze = Object.freeze(obj)

console.log(obj===objFreeze) //-> true

obj.a = 3
console.log(obj.a) //-> 1

// 如果被冻结对象的一个属性的值是个对象,则这个对象中的属性是可以修改的,除非把它冻结
obj.c.d = 4
obj.e[1] = 10
console.log(obj.c.d) // -> 4
console.log(obj.e[1]) //-> 10

Object.isFrozen()

语法:
  Object.isFrozen(obj)

作用:
  判断一个对象是否被冻结

参数:
  obj:被检测的对象

返回值:
  被检测对象是否被冻结的布尔值

原对象是否改变:
  否

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 一个对象默认是可扩展的,所以它也是非冻结的
Object.isFrozen({}) //-> false

// 冻结对象、密封对象都是冻结的
var frozen = { 1: 81 };
Object.isFrozen(frozen) //-> false
Object.freeze(frozen);
Object.isFrozen(frozen) //-> true
Object.isSealed(frozen) //-> true

// 不可扩展对象不一定是冻结对象
// -> 虽然不可扩展,但已有属性仍可以修改
const noObj = { p: 1 }
Object.preventExtensions(noObj)
Object.isFrozen(noObj) //-> false
// -> 不可扩展的空对象,是一个冻结对象
const empty = {}
Object.preventExtensions(empty)
Object.isFrozen(empty) //-> true

// 非对象参数会被视为一个冻结的普通对象,因此会返回 true
Object.isFrozen(1) //-> rue

Object.seal()

语法:
  Object.seal(obj)

作用:
  封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要是原来是可写的就可以改变

参数:
  obj:将要被密封的对象

返回值:
  被密封的对象

原对象是否改变:
  是

描述:
  一个对象通常是可以扩展的。密封会让对象变得不能添加新属性,且已有属性会变得不可配置。属性不可配置的效果就是属性变得不可删除,以及数据属性不能被重新定义为访问器属性。不会影响从原型链上继承得属性

例子:

1
2
3
4
5
6
7
8
9
10
const obj = { a: 1}
const obj2 = Object.seal(obj)

obj === obj2 // true
obj.a = 2 // 可以修改属性值

// 但是不能将属性重新定义为访问器属性
Object.defineProperty(obj,'a',{
get: function() { return 3 }
}) // TypeError

Object.isSealed()

语法
  Object.isSealed(obj)

作用:
  判断一个对象是否被密封

参数:
  obj:要被检查的对象

返回值:
  表示给定对象是否被密封的 Boolean

原对象是否改变:
  否

描述:
  密封对象是指那些不可扩展的,且所有自身属性都不可配置且因此不可删除(但不一定是不可写) 的对象

例子:

1
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
// 新建的对象默认不是密封的
const obj = {}
Object.isSealed(obj) // false

// 单独设置属性为不可配置属性也不是密封的
const obj2 = { a: 1 }
Object.defineProperty(obj2,'a',{
configurable: false
})
Object.isSealed(obj2) // false

// 密封的定义:不可扩展、不可配置
Object.preventExtensions(obj2)
Object.isSealed(obj2) // true

// 还有一点,所有自身属性都不可配置
const obj3 = { a: 1, b: 2 }
Object.preventExtensions(obj3)
Object.defineProperty(obj3, 'a', {
configurable: false
})
Object.isSealed(obj3) // false

Object.defineProperty(obj3, 'b', {
configurable: false
})
Object.isSealed(obj3) // true

Object.preventExtensions()

语法
  Object.preventExtensions(obj)

作用:
  让一个对象变的不可扩展,即不能再添加新的属性。一旦对象变为不可扩展对象,就再也不能使其可扩展

参数:
  obj:要变的不可扩展的对象

返回值:
  已经不可扩展的对象

原对象是否改变:
  是。原对象已不可扩展,包括不能修改原型

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 返回的是不可扩展的原对象
const obj = {}
const obj2 = Object.preventExtensions(obj)
obj === obj2 // true

// 使用 Object.defineProperty 方法为一个不可扩展的对象添加新属性会抛出异常
Object.defindProperty(obj,'a',{value:2}) // TypeError

// 对象不可扩展之后,仍然可以删除
const exObj = {a:1,b:2}
Object.preventExtensions(exObj)
delete exObj.a
console.log(exObj) // {b:2}

Object.isExtensible()

语法:
  Object.isExtensible(obj)

作用:
  判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)

参数:
  obj:需要检测的对象

返回值:
  表示给定对象是否可以扩展的一个布尔值

原对象是否改变:
  否

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 新对象默认是可扩展的
const empty = {}
Object.isExtensible(empty) //-> true

// 以下方法可以变的不可扩展
Object.preventExtensions(empty)
Object.isExtensible(empty) //-> false

// -> 密封对象不可扩展
const sealObj = Object.seal({})
Object.isExtensible(sealObj) //-> false

// -> 冻结对象不可扩展
const freeObj = Object.freeze({})
Object.isExtensible(freeObj) //-> false

// 非对象参数将被视为一个不可扩展的普通对象,因此会返回 false
Object.isExtensible(1) //-> false

原型相关

Object.getPrototypeOf()

语法:
  Object.getPrototypeOf(obj)

作用:
  返回指定对象的原型

参数:
  obj:一个对象

返回值:
  给定对象的原型,如果没有继承属性,则返回 null

原对象是否改变:
  否

例子:

1
2
3
const proto = {}
const obj = Object.create(proto)
Object.getPrototypeOf(obj) === proto // true

Object.setPrototypeOf()

语法:
  Object.setPrototypeOf(obj, prototype)

作用:
  设置一个指定的对象的原型(即内部 [[Prototype]] 属性]到另一个对象或 null

参数:

  • obj:要设置原型的对象
  • prototype:新原型(一个对象或 null)

返回值:
  修改原型后的对象

原对象是否改变:
  是(原型指向改变了)

描述:
  如果对象的 [[Prototype]] 被修改成不可扩展,再去修改的话会抛出 TypeError;如果参数 prototype 不是一个对象活着 null,则什么都不做

例子:

1
2
3
const proto = { a: 1, b: 2 }
const obj = { c: 3, d: 4 }
console.log(Object.getPrototypeOf(Object.setPrototypeOf(obj,proto))===proto) //-> true

对象遍历

Object.keys()

语法
  Object.keys(obj)

作用:
  返回一个由给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致

参数:
  obj:要返回其枚举自身属性的对象

返回值:
  一个表示给定对象的所有可枚举属性的字符串数组

原对象是否改变:
  否

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const arr = ['a', 'b', 'c']
console.log(Object.keys(arr)) // ['0', '1', '2']

const obj = { 0: 'a', 1: 'b', 2: 'c'}
console.log(obj) // ['0', '1', '2']

// 类数组键的排序是随机的
const likeAry = { 100: 'a', 2: 'b', 7: 'c' }
console.log(Object.keys(likeAry)) // ['2', '7', '100']

// getFoo 为一个不可枚举属性
const myObj = Object.create({}, {
getFoo: {
value: function(){return this.foo}
}
})
myObj.foo = 1
console.log(Object.keys(myOjb)) // ['foo']

// es5里,如果参数是一个原始值,会抛出 `TypeError`
Object.keys('foo') // TypeError: 'foo' is not an object
// es6中非对象的参数将被强制转换为一个对象
Object.keys('foo') // ['0', '1', '2']

Object.values()

语法:
  Object.values(obj)

作用:
  返回给定对象自身的所有可枚举属性值的数组,值的顺序与使用for..in循环的顺序相同

参数: obj:一个对象

返回值:
  包含提供对象的自身的所有可枚举属性值的数组

例子:

1
2
3
4
5
6
7
8
9
var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

// 当使用数字键时,根据数字键的顺序进行排序
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']

// 非对象参数将会被强制转换为对象
console.log(Object.values('foo')); // ['f', 'o', 'o']

实例方法

Object.prototype.hasOwnProperty()

语法:
  obj.hasOwnProperty(key)

作用:
  判断对象自身属性中是否有指定的键,有,返回 true;没有,返回 false

参数:

  • obj:检测的对象
  • key:要检测的键

返回值:
  true 或 false

原对象是否改变:
  否

例子:

1
2
3
const obj = { a: 1, b: 2 }
console.log(obj.hasOwnProperty('a')) //-> true
console.log(obj.hasOwnProperty('hasOwnProperty')) //-> false

Object.prototype.isPrototypeOf()

语法
  prototypeObj.isPrototypeOf(object)

作用:
  测试一个对象(prototypeObj)是否存在于另一个对象(object)的原型链上

参数:
  obj:

  • prototypeObj:要搜寻的对象
  • object:被搜寻的对象,即在该对象的原型链上搜寻

返回值:
  表示调用对象是否在另一个对象的原型链上的布尔值

原对象是否改变:
  否

描述:

  • isPrototypeOf() 在对象的原型链上搜寻
  • instanceof A instanceof B,判断构造函数B的prototype是否存在于对象A的原型链上

一个是针对本身检查,一个是针对原型检查

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Foo() { }
function Bar() { }
function Baz() { }

Bar.prototype = Object.create(Foo.prototype)
Baz.prototype = Object.create(Bar.prototype)

var baz = new Baz()

console.log(Baz.isPrototypeOf(baz)); // false
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true

Object.prototype.propertyIsEnumerable()

语法:
  obj.propertyIsEnumerable(key)

作用:
  返回一个布尔值,表示指定的属性是否可枚举

参数:
  key:需要测试的属性名

返回值:
  用来表示指定的属性名是否可枚举的布尔值

原对象是否改变:
  否

例子:

1
2
3
4
const obj = { a: 1 }, ary = [1]
obj.propertyIsEnumerable('a') // true
ary.propertyIsEnumerable(0) // true
ary.propertyIsEnumerable('length') // false

Object.prototype.toLocaleString()

语法:
  obj.toLocaleString()

作用:
  返回一个该对象的字符串表示。此方法被用于派生对象为了特定语言环境的目的而重载使用

参数: obj:一个对象

返回值:
  表示对象的字符串

原对象是否改变:
  否

描述:
  Object 的 toLocaleString 方法返回调用 toString() 的结果。Number、Array、Date 原型上的方法会覆盖对象上提供的此方法

Object.prototype.toString()

语法:
  obj.toString()

作用:
  返回一个表示该对象的字符串

参数: obj:一个对象

返回值:
  表示该对象的字符串

描述:
  默认情况下,toString()方法被每个对象继承。如果此方法在自定义对象中未被覆盖,toString()返回[object type],其中type是对象的类型

Object.prototype.valueOf()

语法:
  obj.valueOf()

作用:
  返回指定对象的原始值

参数: obj:一个对象

返回值:
  该对象的原始值

描述:
  默认情况下,valueOf方法由Object后面的每个对象继承。每个内置的核心对象都会覆盖此方法以返回适当的值。如果对象没有原始值,将返回对象本身

强制数字类型转换和强制基本类型转换优先会调用该方法,而强制字符串转换会调用 toString(),并且 toString() 很可能返回字符串值,因此在这种情况下不会调用 valueOf()

Object.prototype.valueOf() 的基本实现被有意设计为无用的:返回一个对象;其返回值将永远不会被任何基本类型转换算法使用,许多内置对象重写此方法以返回适当的基本类型值。创建自定义对象时,可以重写 valueOf() 来调用自定义方法,以便将自定义对象转换为基本类型值

不同类型对象的 valueOf() 方法的返回值

对象 返回值
Array 返回数组对象本身
Boolean 布尔值
Date 存储的时间是从 1970年1月1日午夜 开始计的毫秒数
Function 函数本身
Number 数字值
Object 对象本身。这里是默认情况
String 字符串值
Maht 和 Error 对象没有 valueOf() 方法

例子:

1
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
35
36
37
38
39
// Array:返回数组对象本身
const ary = [1,2,3]
console.log(ary.valueOf() === ary) // true

// Boolean:返回布尔值
// 1 字面量方式
const bl = true
console.log(bl.valueOf() === bl) // true
// 2 Boolean对象
const blo = new Boolean(true)
typeof blo // 'object'
blo.valueOf() === blo // false blo.valueOf()的返回值是true,两者值相等,但是类型不一样

// Date:返回当前时间距 1970 年 1 月 1 日午夜的毫秒数
const date = new Date() // Mon Jun 27 2022 10:16:10 GMT+0800 (中国标准时间)
date.valueOf() // 1656296293446

// Function:返回函数本身
function foo(){}
console.log( foo.valueOf() === foo ); // true

// Number:返回数字值
let num = 12
num.valueOf() // 12
num = new Number(12)
num.valueOf() // 12
num.valueOf() === num // false 同 Boolean

// Object:返回对象本身
var obj = {name: "张三", age: 18};
console.log( obj.valueOf() === obj ); // true

// String:返回字符串值
var str = "http://www.xyz.com";
console.log( str.valueOf() === str ); // true
// new 一个字符串对象
var str2 = new String("http://www.xyz.com");
// 两者的值相等,但不全等,因为类型不同,前者为 string 类型,后者为 object 类型
console.log( str2.valueOf() === str2 ); // false