Object.defineProperty()
三个参数:监听的对象(obj),属性名(key),属性描述(descriptor )
先理解第三个参数(参数类型:object)
writable :默认false(只读),true为可编辑
let obj = {}
Object.defineProperty(obj, "name", {
value: '张三'
})
console.log(obj.name) // 张三
obj.name = '王老五'
console.log(obj.name) // 张三
let obj = {}
Object.defineProperty(obj, "name", {
value: '张三',
writable: true
})
console.log(obj.name) // 张三
obj.name = '王老五'
console.log(obj.name) // 王老五
enumerable :是否可以被枚举,也就是遍历和使用Object.keys()时能否读取到这个属性值。默认为false(不可枚举),不影响该属性的正常使用和读取。
let obj = {
age: 18,
info: '哈哈'
}
Object.defineProperty(obj, "name", {
value: '张三',
})
let key = Object.keys(obj)
console.log(key) // ['age', 'info']
console.log(obj.name) // 张三
let obj = {
age: 18,
info: '哈哈'
}
Object.defineProperty(obj, "name", {
value: '张三',
})
let key = Object.keys(obj)
console.log(key) // ['age', 'info', 'name']
console.log(obj.name) // 张三
configurable :是否可以被删除和重新定义特性,默认为false(禁止)
let obj = {}
Object.defineProperty(obj, "name", {
value: '张三',
writable: true,
configurable: false
})
console.log(obj.name) // 张三
delete obj.name
console.log(obj.name) // 张三
//结果还在,不可被删除
Object.defineProperty(obj, 'name', {
value: 'Jack',
enumerable: true
})
// 当你写到这儿的时候,控制台报错 :Uncaught TypeError: Cannot redefine property: name
// 无法重新定义name这个属性
// 所以此时需要把前面定义过的configurable的值改为true
set : 当你在设置这个对象属性的值时,会被调用,自带一个参数,参数的来源是给对象属性赋予的值。默认是undefined(没有),若使用则需要自行定义。
let obj = {}
Object.defineProperty(obj, "name", {
set(newVal) {
this.info = newVal
}
})
console.log(`name:${obj.name},info:${obj.info}`) name:undefined,info:undefined
obj.name = "张三大魔王"
console.log(`name:${obj.name},info:${obj.info}`) name:undefined,info:张三大魔王
注意点:
1.不能和value和writable同用(未捕获的类型错误:无效的属性描述符。 不能同时指定访问器和值或可写属性)
2.赋值对象不能是第二参数
let obj = {}
Object.defineProperty(obj, "name", {
set(newVal) {
this.name = newVal
}
})
obj.name = "张三大魔王"
// Uncaught RangeError: Maximum call stack size exceeded
// 超出最大调用堆栈大小
// 百度了解后,意思是obj.name = '' 调用了set方法,set方法里this.name = newVal转换
// 后也就等价于obj.name = newVal,那么进行了赋值操作此时又要调用set方法,由此形成
// 一个回调上的死循环
get 当读取对象属性的值时调用,通过return返回内容,可以返回任意类型
let obj = {
name: 'zs'
}
console.log(obj.name) // zs
Object.defineProperty(obj, "name", {
get() {
return 2
}
})
console.log(obj.name) // 2
注意点:
1.与set一样不能和writable以及value同时出现
2.由例子中看出,可以改变它之后的对象属性的读取内容
第二个参数(参数类型:string)
可以是新增属性,也可以直接对已有属性进行编辑
第一个参数
只能是一个对象,不能写null
这里像Math、Array、Date等都属于Object对象,也是可以作为参数使用
let arr = [1, 2, 3]
Object.defineProperty(Math, 'info', {
value: 32
})
Object.defineProperty(arr, 'info', {
value: 32
})
console.log(Math.info) // 32
console.log(arr.info) // 32
Object.defineProperties()
个人理解是Object.defineProperty()的复合写法,可一次性对多个属性进行批量操作。
let obj = {
name: 'zs'
}
console.log(obj.name) // zs
Object.defineProperties(obj, {
'name': {
value: 22,
writable: true
},
'info': {
get() {
return 'sorry'
}
},
'age': {
set(newVal) {
this.blue = newVal
}
}
})
console.log(obj.name) // 22
console.log(obj.info) // sorry
obj.age = 19
console.log(obj.age, obj.blue) // undefined 19
Object.create()
使用指定原型对象及其属性去创建一个新对象
什么意思呢?先看这个方法有几个参数:
第一个参数:指定新对象的原型对象,可以为null,也可以普通对象或某个构造函数的原型对象,但不能不写。
第二个参数:给新对象的赋予属性,写法和defineProperties的复合写法一样。
let obj = {
name: 'zs'
}
console.log(obj.__proto__) // 指向Object的原型对象
let newObj = Object.create(null, {
a: {
value: '我是A'
},
b: {
set(newVal) {
this.info = '我是由B赋值的'
}
}
})
newObj.b = '我是B'
console.log(newObj.a, newObj.b, newObj.info) // 我是A undefined 我是由B赋值的
console.log(newObj.__proto__) // undefined
由这个例子可以看出这个使用create创建的新对象的原型对象是需要人为指定的。
// 此时将第一个参数更换一下试试呢?
var newObj = Object.create(Object.prototype)
// {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
var newObj = Object.create(Object)
// Object() { [native code] }
var newObj = Object.create({name:'zs'})
// {name: 'zs'}
可以看出这个create方法比较重要的是第一个参数,第二个参数可以为空,之后添加新属性就和平时对对象的操作一样,也可以使用前两个。
Object.keys(object) 和 Object.values(object)
返回一个对象所有属性的数组/返回一个对象所有属性值的数组
let obj = {
name: 'zs',
age: 17
}
Object.defineProperty(obj, 'info', {
value: 32
})
let keys = Object.keys(obj)
let val = Object.values(obj)
console.log(keys, val) // ['name', 'age'] ['zs', 17]
console.log(obj) // {name: 'zs', age: 17, info: 32}
注意,通过defineProperty、defineProperties、和create第二个参数,创建的属性,如果不设置enumerable属性,那么keys和values都将获取不到。
Object.entries()
keys()和values()的合并版
let obj = {
name: 'zs',
age: 18,
info: '我是对象'
}
let kv = Object.entries(obj)
console.log(kv)
// [['name', 'zs'],['age', 18],['info', '我是对象']]
// 不能获取enumerable:false的属性
Object.assign()
对象的合并,一个主参数,和其他被合并的对象。
let obj = {
name: 'zs',
age: 17
}
let obj2 = {
info: '我是第二个对象'
}
Object.assign(obj, obj2)
console.log(obj) // {name: 'zs', age: 17, info: '我是第二个对象'}
let obj = {
name: 'zs',
age: 17
}
let arr = [
[1, 1, 1], 2, 3
]
Object.assign(obj, arr)
console.log(obj) // {0: Array(3), 1: 2, 2: 3, name: 'zs', age: 17}
以数组为参数时,把数组的下标作为属性名,元素作为值。
拷贝时如果有重复的属性,后面的把前面的覆盖。
应用场景:
let box = document.querySelector('div')
Object.assign(box.style, {
width: '100px',
height: '100px',
background: 'skyblue'
})
// style也是一个属性,所以也可以用此方法快速赋值,节省重复的代码
image.png
hasOwnProperty(key)
判断对象中有无该属性,有则返回true,反之false
obj.hasOwnProperty('name') // true
//注意参数必须是字符串或者赋值后的变量
(未完待续……)
目前根据学习程度,代码中使用频率较高的只总结到这个地步,若往后有用到的再补充。
有兴趣的可以点击下方链接继续深度学习。
- PS: *defineProperty详解:https://www.cnblogs.com/ldq678/p/13854113.html
- PS: *Object常用方法:https://www.cnblogs.com/mopagunda/p/8328084.html










网友评论