Skip to content

Object 对象

  1. 创建方式--3 种

字面量方式

js
var obj = {}

console.log(typeof obj); // object console.log(obj instanceof Object); //true console.log(Object.prototype.toString.call(obj)); //[object Object]

构造函数

js
var obj2 = new Object()
console.log(typeof obj2) //object
console.log(obj2 instanceof Object) //true
console.log({}.toString.call(obj2)) //[object Object]

静态方法

js
var obj3 = Object.create(null)
console.log(typeof obj3) //object
console.log(obj3 instanceof Object) //false
console.log({}.toString.call(obj3)) //[object Object]
  1. {} 与 Object.create(null)的区别
  • new Object() :

{}

  • Object.create(null):

Object.create(null)

  1. 方法

定义方法

Object.create()

创建一个新对象,使用现有的对象来提供新创建的对象的proto

js
var newObj = Object.create(proto, [propertiesObject])
入参:
  • proto :新对象原型对象
  • propertiesObject : 新对象的属性(propertiesObject)
出参:
  • targetObj :创建的新的对象
: IE9+ ,ES6 新方法
js
var obj = {
  name: "gzh",
}
obj.prototype = {
  changeName: function (newName) {
    this.name = newName
  },
}
console.log(
  Object.create(obj, {
    age: {
      writable: true,
      configurable: true,
      value: 26,
    },
  })
)

image-20230213132240073

对象的继承
js
function Animal(name) {
  this.name = name
}
Animal.prototype.getName = function () {
  return this.name
}
function Dog(name) {
  this.type = "dog"
  this.name = name
}
Dog.prototype = Object.create(Animal.prototype)
Dog.prototype.constructor = Dog
var dog = new Dog("dog1")
console.log(dog) //dog1

image

创建一个没有原型的对象
js
var obj = Object.create(null)
var obj1 = {}

image

枚举方法

1、 可枚举属性???

方法说明
Object.keys()获取对象属性名组成的数组
Object.values()获取对象属性值组成的数组
Object.entries()获取对象[属性名,属性值]组成的数组
  • Object.keys()
  • Object.values()
  • Object.entries()

3.1、Object.keys()

返回一个由一个给定对象的组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。

js
var keyArr = Object.keys(obj)
入参:
  • obj :枚举的对象
出参:
  • keyArr : 一个表示给定对象的所有可枚举属性的字符串数组。
: IE9+ , ES6 新方法
js
var obj = Object.defineProperties(
  { name: "gzh" },
  {
    age: {
      writable: true,
      configurable: true,
      enumerable: true,
      value: 26,
    },
    address: {
      enumerable: false,
      writable: true,
      value: "北七",
    },
  }
)
console.log(Object.keys(obj)) // ['name','age']  address 没有出现  因为其不可枚举
console.log(obj)
console.log(Object.getOwnPropertyDescriptor(obj, "address").enumerable) //false

image

3.2、Object.values()

返回一个由一个给定对象的值组成的数组,数组中值的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。

js
var keyArr = Object.values(obj)
入参:
  • obj :枚举的对象
出参:
  • keyArr : 一个包含对象自身的所有可枚举属性值的数组。
: IE 不支持 但是 ES6 新方法
js
var obj = Object.defineProperties(
  { name: "gzh", otherInfo: { id: 12312 } },
  {
    age: {
      writable: true,
      configurable: true,
      enumerable: true,
      value: 26,
    },
    address: {
      enumerable: false,
      writable: true,
      value: "北七",
    },
  }
)
console.log(Object.values(obj)) // ['gzh',{id : 12312},26]  '北七' 没有出现  因为其不可枚举
console.log(obj)
console.log(Object.getOwnPropertyDescriptor(obj, "address").enumerable) //false

3.2、Object.entries()

返回一个对象 的 键值对数组 ,数组中值的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。

js
var keyArr = Object.entries(obj)
入参:
  • obj :枚举的对象
出参:
  • keyArr : 一个对象自身可枚举属性 的 键值对数组。
: IE 不支持 但是 ES6 新方法
js
var obj = Object.defineProperties(
  { name: "gzh" },
  {
    age: {
      writable: true,
      configurable: true,
      enumerable: true,
      value: 26,
    },
    address: {
      enumerable: false,
      writable: true,
      value: "北七",
    },
  }
)
console.log(Object.entries(obj)) // [['name','gzh'] , ['age',26 ] ] address 没有出现  因为其不可枚举

操作方法

方法说明
Object.assign()复制多个目标对象的可枚举属性,并返回目标对象
Object.is()判断两个对象是否相等
Object.freeze()冻结一个对象
Object.isFrozen()判断对象是否是冻结对象

Object.assign()

将一个或者多个源目标中 所有的值 复制到 目标对象,并返回目标对象

js
var targetObj = Object.assign(targetObj, sourceObj1...);
入参:
  • targetObj :目标对象
  • sourceObj1... : 一个或者多个源对象
出参:
  • targetObj :赋值后的目标对象
1、 是最后一个源对象数据覆盖前一个源对象相同属性的值。
2、 只复制源对象中 属性的 值。
3、 Object.assign() 拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。(
: IE 不支持 但是 ES6 新方法
js
const a = {}
const b = Object.assign(a, { name: "gzh", address: "北七" }, { name: "gzh1" })
console.log(a) // {address : '北七', age : 26 , name : 'gzh1'}
console.log(b)
console.log(a === b) // a 和 b 指向同一个对象地址
只复制可枚举属性的值
js
var obj = Object.create(
  { foo: 1 },
  {
    // foo 是个继承属性。
    bar: {
      value: 2, // bar 是个不可枚举属性。
    },
    baz: {
      value: 3,
      enumerable: true, // baz 是个自身可枚举属性。
    },
  }
)

var copy = Object.assign({}, obj)
console.log(copy) // { baz: 3 }

Object.is()

判断两个值是否相同

js
var boolean = Object.is(value1, value2)
入参:
  • value1 :比较对象 1
  • value2 : 比较对象 2
出参:
  • boolean :是否相同
  1. 与 == 的区别
  • == 会对两边的值进行隐式类型转换。
  1. 与 ===, == 的区别
  • -0 === +0 , -0 == +0 , Object.is(+0 , -0) === false
  • NaN !== NaN , NaN != NaN , Object.is(NaN , NaN) === true
: IE 不支持 , ES6 新方法
js
console.log(Object.is(-0, +0)) //false
console.log(-0 === +0) //true
console.log(NaN === NaN) //false
console.log(Object.is(NaN, NaN)) //true
ES5 实现 Object.is 方法
js
Object.defineProperty(Object, "is", {
  configurable: true,
  enumerable: false,
  writable: true,
  value: function (x, y) {
    //  针对  -0 === +0
    if (x === y) {
      return x !== 0 && 1 / x === 1 / y
    }
    // 针对 NaN !== NaN
    if (x !== y) {
      return x !== x && y !== y
    }
  },
})

Object.freeze(),Object.isFrozen()

冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。该方法返回被冻结的对象。 Object.isFrozen() 判断对象是否是冻结对象

js
var freezeObj = Object.freeze(obj)
js
var obj = {
  name: "gzh",
  getName() {
    return this.name
  },
}

var freezeObj = Object.freeze(obj)

try {
  freezeObj.name = "12"
  delete freezeObj.getName

  Object.defineProperty(freezeObj, "name", {
    value: 23,
  })
} catch (e) {
  console.log(e)
}
console.log(freezeObj)
Object.isFrozen()
js
console.log(Object.isFrozen(obj)) //false
console.log(Object.isFrozen(freezeObj)) //true

对象属性的概念

任意一个对象的每一个属性其实都是一个属性描述对象,其存在 configurable、enumerable、writable、value、get、set 6 个属性

js
var obj = {
  name: "gzh",
}
console.log(Object.getOwnPropertyDescriptor(obj, "name"))
// {
//     value: "gzh",
//     writable: true,
//     enumerable: true,
//     configurable: true
// }

可见 对象属性的默认描述符对象为 configurable: true,enumerable: true, writable: true,value: "gzh"

--configurableenumerablewritablevaluegetset
数据描述符truetruetruetruefalsefalse
存储描述符truetruefalsefalsetruetrue

configurable

true : 该属性的属性描述符能够被修改,且能够被删除 false : 属性描述符不能被修改,属性不能删除(默认)

js
var obj = {
  name: "gzh",
}
Object.defineProperty(obj, "age", {
  configurable: false,
  enumerable: false,
  writable: false,
  value: 26,
})

delete obj.name
delete obj.age
console.log(obj) // { age: 26}  name被删除了、age没有被删除。
Object.defineProperty(obj, "age", {
  // Cannot redefine property: age 报错
  value: 28,
})

enumerable 是否可被枚举

true : 该属性才能够被枚举 false : 不能被枚举 (默认)

涉及到枚举的如 for...in , Object.keys() , Object.values() , Object.entries(), JSON.stringify() , Object.assign()

js
var obj = {
  name: "gzh",
}
Object.defineProperty(obj, "age", {
  configurable: false,
  enumerable: false,
  writable: false,
  value: 26,
})

delete obj.name
delete obj.age
console.log(obj) // { age: 26}  name被删除了、age没有被删除。
Object.defineProperty(obj, "age", {
  // Cannot redefine property: age 报错
  value: 28,
})

writable 是否可被赋值运算符修改,value 当前的值

true : 该属性可以被修改 false : 不能被修改(默认)

value : 值 默认为 undefined

js
var obj = {
  name: "gzh",
}
Object.defineProperty(obj, "age", {
  configurable: false,
  enumerable: false,
  writable: false,
  value: 26,
})

get、set

get(){} 获取属性的值 set(val){}设置属性的值

js
var address = "",
  logs = []

Object.defineProperty(obj, "address", {
  get() {
    return `您的地址为:${address}。`
  },
  set(val) {
    address = val
    logs.push({
      val: val,
    })
  },
})
obj.address = "南京"
console.log(obj.address)
console.log(logs)
  1. writable、value 与 get、set 不能同时出现
js
var address = ""
// 报错: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute
Object.defineProperty(obj, "address", {
  configurable: false,
  enumerable: false,
  writable: false,
  value: 26,
  get() {
    return address
  },
})
  1. set get 不要通过 this 去操作
js
var address = ""

Object.defineProperty(obj, "address", {
  configurable: true,
  enumerable: true,
  get() {
    return this.address
  },
  set(val) {
    this.val = val
  },
})
obj.address = "南京" // Maximum call stack size exceeded ???
// 因为 obj.address赋值的时候 执行到 this.val = val;的时候又会触发set方法,再次执行...无限循环
// get 一样

枚举属性和不可枚举属性

什么是枚举属性?什么是不可枚举属性

1、 对于 Object.defineProperty()的描述属性对象中的 enumerable:true 的为可枚举属性,false 就是不可枚举属性 2、 对于通过如 for...in 遍历不到的属性 就是不可枚举属性。 3、 obj.propertyIsEnumerable() 为 true 的为可枚举属性

js
var obj = {}

for (var key in obj) {
  console.log(key + ": " + obj[key]) //为空 那么其继承的哪些属性哪去了
}
console.log(Object.keys(obj)) // name  其他的如 job都没有
console.log(JSON.stringify(obj)) //{"name":"fun1Name"}
console.log(obj.propertyIsEnumerable("toString")) // false

哪些是不可枚举的?

  • 原型上的属性方法都是不可枚举的。
  • Object.defineProperty(obj,prop,{ enumerable : false })

如何判断属性方法是不可枚举的

  • Object.getOwnPropertyDescriptor(obj,'name').enumerable === false
  • obj.propertyIsEnumerable(prop) === true
  1. 存在于对象原型里面的属性 其都是不可枚举的 obj.propertyIsEnumerable() 返回值为 false
  2. 设置 对象属性不可枚举 使用 Object.defineProperty(obj,key,{ enumerable:false})
  3. 不可枚举的对象属性 使用 for in , Object.keys() , JSON.stringify() 都获取不到 ,但是可以用 obj[key]获取
  4. Object.assign() 只能 copy 一个或多个 目标对象 的 可枚举属性 到源对象

5. 属性方法

方法说明
Object.defineProperty()定义单个属性的属性描述对象
Object.defineProperties()定义对象多个属性的属性描述对象
Object.getOwnPropertyDescriptor()获取自身单个属性的属性描述对象
Object.getOwnPropertyDescriptors()获取自身所有的属性描述对象
obj.propertyIsEnumerable()判断每一个属性是否可枚举(原型链上可以)

5.1 Object.defineProperty()

会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

js
    var oldObj = Object.defineProperty(obj,key,descriptor{})
入参:
  • obj : 目标对象
  • key : 操作的属性
  • descriptor : 属性的描述符
    • 详情见上面属性描述符详解
出参:
  • oldObj : 修改后的属性对象
js
var obj = {
  name: "obj",
}
Object.defineProperty(obj, "age", {
  configurable: false,
  value: 26,
})
console.log(Object.getOwnPropertyDescriptor(obj, "age")) //{value: 26, writable: false, enumerable: false, configurable: false}
// {
//     value: 26,
//     writable: false,    // 没有定义默认为false
//     enumerable: false,  // 没有定义默认为false
//     configurable: false
// }
console.log(Object.getOwnPropertyDescriptor(obj, "name")) //{value: "obj", writable: true, enumerable: true, configurable: true}
// {
//     value: "obj",
//     writable: true,    不是通过Object.defineProperty定义的属性其默认是true
//     enumerable: true,  // 没有定义默认为false
//     configurable: true
// }
  1. Object.defineProperty() 定义的属性其 configurable、enumerable、writable 默认为 false。
  2. 通过 obj.address = "阿萨"等 没有设置其属性描述符的其默认为 true, {value: "obj", writable: true, enumerable: true, configurable: true}

Object.defineProperties

会直接在一个对象上定义多个新属性,或者修改多个现有属性, 并返回这个对象。

js
var oldObj = Object.defineProperties(obj, {})
入参:
  • obj : 目标对象
  • prop : descriptor 属性的描述符
出参:
  • oldObj : 修改后的属性对象
js
Object.defineProperties(obj, {
  age: {
    configurable: true,
    value: 26,
  },
  address: {
    value: "这是地址",
  },
})

Object.getOwnPropertyDescriptor() , Object.getOwnPropertyDescriptors()

获取对象自身属性的属性描述符对象。

js
var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
var descriptors = Object.getOwnPropertyDescriptors(obj)
入参:
  • obj : 目标对象
  • prop : 属性名称
出参:
  • descriptor : 属性描述对象
js
var obj = {
  name: "obj",
}
var age = 12
Object.defineProperties(obj, {
  age: {
    configurable: false,
    get: function () {
      return age
    },
    set: function (val) {
      console.log(this) // this指向obj对象,但是不能通过this.age = val去设置value,不然会无限触发set函数
      age = val
    },
  },
})
console.log(Object.getOwnPropertyDescriptors(obj))
//{"name":{"value":"obj","writable":true,"enumerable":true,"configurable":true},"age":{"enumerable":false,"configurable":false}}
// 可见我们定义一个对象的属性的时候其已经默认设置了 {"value":undefined,"writable":true,"enumerable":true,"configurable":true}
console.log(Object.getOwnPropertyDescriptor(obj, "name"))
//{"name":{"value":"obj","writable":true,"enumerable":true,"configurable":true}}

obj.propertyIsEnumerable()

返回对象的某一个属性是否是可枚举属性

js
var boolean = obj.propertyIsEnumerable(obj, prop)
入参:
  • obj : 目标对象
  • prop : 属性名称
出参:
  • boolean : 对象的其属性是否是可枚举属性
js
var obj = {
  name: "gzh",
}
console.log(Object.getOwnPropertyDescriptors(obj)) // {name : {enumerable: true}}
console.log(obj.propertyIsEnumerable("name")) // true
console.log(obj.propertyIsEnumerable("toString")) // false

原型方法

方法说明
Object.getPrototypeOf()获取指定对象的原型对象,__proto__
Object.getOwnPropertyNames()获取指定对象自身属性名组成的数组
obj.hasOwnProperty()判断 obj 对象自身属性中是否存在指定的属性
obj.isPrototypeOf()判断 obj 是否是目标对象原型链中的属性

Object.getPrototypeOf()

获取指定对象的原型属性 即proto的值 ,没有则返回 null。

js
var obj = Object.getPrototypeOf(obj)
入参:
  • obj : 目标对象
出参:
  • obj : 指定对象的原型属性 即proto的值 ,没有则返回 null。
js
var obj = {}
var emptyObj = Object.create(null)

console.log(Object.getPrototypeOf(obj)) // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …} 即__proto__ 的值
console.log(Object.getPrototypeOf(emptyObj)) // null 因为Object.create()创建的对象继承的就是其原型属性,null没有原型所以为null

Object.getOwnPropertyNames()

返回指定对象的所有的属性名组成的数组。(

js
var propertyArray = Object.getOwnPropertyNames(obj)
入参:
  • obj : 目标对象
出参:
  • propertyArray : 指定对象的所有自身属性的属性名组成的数组。
js
var obj = {
  name: "obj",
}
var symbol = Symbol()
obj[symbol] = "symbol"
var age = 12
Object.defineProperties(obj, {
  age: {
    configurable: false,
    enumerable: false,
    get: function () {
      return age
    },
    set: function (val) {
      console.log(this) // this指向obj对象,但是不能通过this.age = val去设置value,不然会无限触发set函数
      age = val
    },
  },
})
console.log(obj)
console.log(Object.getOwnPropertyNames(obj)) // ['name','age']  没有Symbol()作为名称的属性,包含了enumerable:false不可枚举的属性,另外不包含prototype原型上的属性

obj.hasOwnProperty()

判断对象中是否包含指定名称的属性(包含不可枚举的,属性名为 Symbol 的)

js
var boolean = obj.hasOwnProperty(propName)
入参:
  • obj : 目标对象
  • propName : 属性名称
出参:
  • boolean : 是否包含此属性。
js
var obj = {
  name: "obj",
}
var symbol = Symbol()
obj[symbol] = "symbol"
var age = 12
Object.defineProperties(obj, {
  age: {
    configurable: false,
    enumerable: false,
    get: function () {
      return age
    },
    set: function (val) {
      console.log(this) // this指向obj对象,但是不能通过this.age = val去设置value,不然会无限触发set函数
      age = val
    },
  },
})
console.log(obj.hasOwnProperty("name")) //true
console.log(obj.hasOwnProperty("age")) //true
console.log(obj[symbol]) //symbol
console.log(obj.hasOwnProperty(symbol)) //true
console.log(obj.hasOwnProperty("constructor")) //false  原型链上的构造函数属性
// console.log(1.hasOwnProperty('constructor'))  //Uncaught SyntaxError: Invalid or unexpected token  非对象获取其自身属性报错

obj.isPrototypeOf()

判断对象中是否包含指定名称的属性(包含不可枚举的,属性名为 Symbol 的)

js
var boolean = obj.hasOwnProperty(propName)
入参:
  • obj : 目标对象
  • propName : 属性名称
出参:
  • boolean : 是否包含此属性。
js
var obj = {
  name: "obj",
}
var symbol = Symbol()
obj[symbol] = "symbol"
var age = 12
Object.defineProperties(obj, {
  age: {
    configurable: false,
    enumerable: false,
    get: function () {
      return age
    },
    set: function (val) {
      console.log(this) // this指向obj对象,但是不能通过this.age = val去设置value,不然会无限触发set函数
      age = val
    },
  },
})
console.log(obj.hasOwnProperty("name")) //true
console.log(obj.hasOwnProperty("age")) //true
console.log(obj[symbol]) //symbol
console.log(obj.hasOwnProperty(symbol)) //true
console.log(obj.hasOwnProperty("constructor")) //false  原型链上的构造函数属性
// console.log(1.hasOwnProperty('constructor'))  //Uncaught SyntaxError: Invalid or unexpected token  非对象获取其自身属性报错

转换方法

  • obj.toString()
  • obj.toLocaleString()
  • obj.valueOf()

obj.toString()

返回一个表示该对象类型的字符串 '[object type]' type 代表对象的类型。 默认每一个类型都存在 toString()且返回该类型字符串,但是所有类型的 toString() 都进行了自定义 所以获取数据的类型 Object.prototype.toString.call(value);

js
console.log({}.toString()) // [object Object]
console.log({ name: "gzh" }.toString()) // [object Object]
console.log("".toString()) // ''
// console.log(null.toString())    // 报错。null没有toString方法
// console.log(undefined.toString())    // [object Object]
console.log((12).toString()) // 12
console.log(true.toString()) // true
console.log(function () {}.toString()) // function(){}
console.log([].toString()) // ''
console.log(/\d+/.toString()) // /\d+/