对象
对象是JavaScript中一个非常重要的概念,这是因为对象可以将多个相关联的数据封装到一起,更好的描述一个事物,JavaScript其实支持多种编程范式的,包括函数式编程和面向对象编程。
如何创建一个对象
早期使用创建对象的方式最多的是使用Object类,并且使用new关键字来创建一个对象:
这是因为早期很多JavaScript开发者是从Java过来的,它们也更习惯于Java中通过new的方式创建一个对象;
// 1.创建方式一: 通过new Object()创建
var obj = new Object()
obj.name = "kangkang"
obj.age = 18
obj.height = 1.88
obj.running = function() {
console.log(this.name + "在跑步~")
}
后来很多开发者为了方便起见,都是直接通过字面量的形式来创建对象:
这种形式看起来更加的简洁,并且对象和属性之间的内聚性也更强,所以这种方式后来就流行了起来;
// 2.创建方式二: 字面量形式
var info = {
name: "mike",
age: 18,
height: 1.98,
eating: function() {
console.log(this.name + "在吃东西~")
}
}
对象属性操作的控制
var obj = {
name: "kangkang",
age: 18
}
// 获取属性
console.log(obj.name)
// 给属性赋值
obj.name = "mike"
console.log(obj.name)
// 删除属性
// delete obj.name
// console.log(obj)
// 需求: 对属性进行操作时, 进行一些限制
// 限制: 不允许某一个属性被赋值/不允许某个属性被删除/不允许某些属性在遍历时被遍历出来
// 遍历属性
for (var key in obj) {
console.log(key)
}
// for in 用来遍历对象
// 要注意 for in 会遍历原型链上的属性 for(var key in obj){
// 使用for in 会遍历到原型链上的属性 这里要进行一下过滤才可以 if( obj.hasOwnProperty(key) ) { console.log(obj[key]) } }
// 顺带提一下for of(用来遍历数组)
//for (var item of arr) //arr 不能是对象,因为对象是不可迭代的
//但可以遍历数组,并且item已经是值了,而不是属性名
//for of 和for in的另外一点不同是:for of 不会遍历目标原型链上的属性
对象属性描述符
如果我们想要对一个属性进行比较精准的操作控制,那么我们就可以使用属性描述符。 通过属性描述符可以精准的添加或修改对象的属性,属性描述符需要使用 Object.defineProperty 来对属性进行添加或者修改。
Object.defineProperty(obj,prop,descriptor)
功能:方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。如果不指定configurable, writable, enumerable ,则这些属性默认值为false,如果不指定value, get, set,则这些属性默认值为undefined。 obj要定义属性的对象
prop 要定义或修改属性的名称 或 Symbol
descriptor 要定义或修改的属性描述符
返回值 被传递给函数的对象
数据属性描述符
数据属性描述符四个配置
-
【configurable】表示属性是否可以通过delete删除,是否可以重新定义属性描述符,或者是否可以将它修改为存取属性描述符;
- 当我们直接在一个对象上定义某个属性时,这个属性的configurable为true
- 当我们通过属性描述符定义某个属性时,这个属性的configurable为false
-
【enumerable】 表示是否可以通过for-in和Object.keys()返回该属性
- 当我们直接在一个对象上定义某个属性时,这个属性的enumerable为true
- 当我们通过属性描述符定义某个属性时,这个属性的enumerable为false
-
【writable】 表示是否可以修改属性的值
- 当我们直接在一个对象定义某个属时,这个属性的writable为true
- 当我们通过属性描述符定义某个属性时,这个属性的writable为false
-
【vaule】 属性的value值,读取属性时返回该值,修改属性时会对其修改
- 默认都是undefined
var obj = {
name: "kangkang",
age: 18
};
// 如果使用数据属性描述符 用了value, 不能使用get/set
Object.defineProperty(obj,"address",{
// 是否可以删除、是否可以重新定义属性描述符、是否可以修改为存取属性描述符 默认值 false
configurable: true,
// 可枚举的 (能被遍历) 默认值 false
enumerable: true,
// 可以写入 (能修改属性) 默认值 false
writable: true,
// 设置值 默认值 undefined
value: "北京市"
})
存取属性描述符
// 1.隐藏某一个私有属性被希望直接被外界使用和赋值
// 2.如果我们希望截获某一个属性它访问和设置值的过程时, 也会使用存储属性描述
var obj = {
name: "kangkang",
age: 18,
_address:'北京市'
}
// 如果使用存取属性描述符 用了get/set, 不能使用writable/value
// 有人读取address会触发get 有人写入address会触发set
Object.defineProperty(obj, "address", {
// 可配置的 (能删除属性) 默认值 false
configurable: true,
// 可枚举的 (能被遍历) 默认值 false
enumerable: true,
get() {
// 获取属性的时候会自动调用get
console.log('get')
return this._address
},
set(value) {
// 设置属性的时候会自动调用set
this._address = value
}
})
定义多个属性描述符
- Object.defineProperties(obj, props)
功能: 方法直接在一个对象上定义一个或多个新的属性或修改现有属性,并返回该对象。
obj: 将要被添加属性或修改属性的对象
props: 该对象的一个或多个键值对定义了将要为对象添加或修改的属性的具体配置
返回值 被传递给函数的对象
var obj = {
_address:''
};
Object.defineProperties(obj, {
age: {
// 是否可以删除、是否可以重新定义描述符
configurable: true,
enumerable: true,
writable: true,
value: 18
},
address: {
// 是否可以删除、是否可以重新定义描述符
configurable: true,
enumerable: true,
get() {
return _address;
},
set(value) {
// 设置address 的时候赋值给_address
this._address = value;
}
}
})
获取对象属性描述符
var obj = {
_address:''
};
Object.defineProperties(obj, {
age: {
// 是否可以删除、是否可以重新定义描述符
configurable: true,
enumerable: true,
writable: true,
value: 18
},
address: {
// 是否可以删除、是否可以重新定义描述符
configurable: true,
enumerable: true,
get() {
return _address;
},
set(value) {
// 设置address 的时候赋值给_address
this._address = value;
}
}
})
//获取单个 属性描述符
console.log( Object.getOwnPropertyDescriptor(obj,"age"))
// 获取整个对象的属性描述符
console.log( Object.getOwnPropertyDescriptors(obj))
Object其他的一些方法
var obj = {
name: 'kangkang',
age: 18
}
// 1.禁止对象继续添加新的属性
Object.preventExtensions(obj)
obj.xxx = 'xxx' //无法添加
// 2.用for fo遍历对象的key 和 value
// Object.entries(obj)
// 返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)
for (var [key, value] of Object.entries(obj)) {
console.log(key, value)
}
// 3.禁止对象配置/删除里面的属性 for of
// for (var [key, value] of Object.entries(obj)) {
// Object.defineProperty(obj, key, {
// configurable: false,
// enumerable: true,
// writable: true,
// value: obj[key]
// })
// }
// 4.禁止对象配置/删除里面的属性 for in
// for (var key in obj) {
// if (obj.hasOwnProperty(key)) {
// Object.defineProperty(obj, key, {
// configurable: false,
// enumerable: true,
// writable: true,
// value: obj[key]
// })
// }
// }
// 5.让属性不可配置 configurable 都为 false
Object.seal(obj)
// 6.让属性不可以修改 writable 都为 false
Object.freeze(obj)
// 7.获取对象的长度 keys()方法只能遍历自己的对象上的可枚举的属性,不能遍历自己原型上可枚举的属性:
console.log(Object.keys(obj).length)
// 获取一个对象的所有自身属性的描述符。
console.log(Object.getOwnPropertyDescriptors(obj))
//更多API请参考MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object