Appearance
Object 对象
- 创建方式--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]
- {} 与 Object.create(null)的区别
- new Object() :
- Object.create(null):
- 方法
定义方法
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,
},
})
)
对象的继承
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
创建一个没有原型的对象
js
var obj = Object.create(null)
var obj1 = {}
枚举方法
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 : 一个表示给定对象的所有可枚举属性的字符串数组。
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
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 :是否相同
- 与 == 的区别
==
会对两边的值进行隐式类型转换。
- 与 ===, == 的区别
-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"
-- | configurable | enumerable | writable | value | get | set |
---|---|---|---|---|---|---|
数据描述符 | true | true | true | true | false | false |
存储描述符 | true | true | false | false | true | true |
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)
- 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
},
})
- 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
- 存在于对象原型里面的属性 其都是不可枚举的 obj.propertyIsEnumerable() 返回值为 false
- 设置 对象属性不可枚举 使用 Object.defineProperty(obj,key,{ enumerable:false})
- 不可枚举的对象属性 使用 for in , Object.keys() , JSON.stringify() 都获取不到 ,但是可以用 obj[key]获取
- 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
// }
Object.defineProperty()
定义的属性其 configurable、enumerable、writable 默认为 false。- 通过 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+/