Object.defineProperty()方法
1、mdn地址
2、Object.definePropery默认:
configurable:false //当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
enumerable:false
value:undefined //很好理解,只声明不赋值,值就是undefined
writable:false //当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。 默认为 false。
get:undefined // 属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
默认为 undefined。set:undefined // 属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
默认为 undefined。
3、对象属性的可枚举性 enumerable
for..in循环 :只遍历对象自身的和继承的可枚举的属性
Object.keys方法 :返回对象自身的所有可枚举的属性的键名
JSON.stringify方法:只串行化对象自身的可枚举的属性
Object.assign()(ES6)
1、for...in 和 Object.keys
- for...in会返回继承的属性。
- for...in循环和Object.keys方法的区别:
(1)前者包括对象继承自原型对象的属性,
(2)后者只包括对象本身的属性。如果需要获取对象自身的所有属性,不管enumerable的值,可以使用
let Parent = function () {
this.name = '888',
this.say = function () {
console.log('say---')
}
}
let Children = function () { }
Children.prototype = new Parent()
let p = new Parent()
let c = new Children()
p.say()
c.say()
for (let item in p) {
console.log("item", item)
// 打印结果
// 第一次:item name
// 第二次:item say
}
for (let cItem in c) {
console.log("cItem", cItem)
// 打印结果
// 第一次:item name
// 第二次:item say
}
console.log("p keys", Object.keys(p))
// 打印结果
// p keys ["name","key"]
console.log("c keys", Object.keys(c))
// 打印结果
// c keys []
2、JSON.stringify
- 只串行化对象自身的可枚举的属性,继承来的属性并不会被转化成字符串
- 再次使用JSON.parse 拿到的对象会发现,新对象并没有元对象继承的属性和方法
let Father = function () {
this.lastName = 'zhang'
this.country = 'China'
}
let Children = function () {
}
Children.prototype = new Father()
let f = new Father()
let c = new Children()
console.log(f)
/*
* country: "China"
* lastName: "zhang"
* __proto__: Object
*/
console.log(c)
/*
* __proto__: Father
*/
console.log(JSON.stringify(f)) //{"lastName":"zhang","country":"China"}
console.log(JSON.stringify(c)) //{}
let f2 = JSON.parse(JSON.stringify(f))
let c2 = JSON.parse(JSON.stringify(c))
console.log("f2 lastName:", f2.lastName) //zhang
console.log("c2 lastName:", c2.lastName) // undefined
3、Object.assign()
- 没什么神奇的,得到的新对象和原来的对象继承一样的属性和方法,原型是一样的,由此可以看出为啥vue中要使用这个方法更改对象了
let a = Object.assign({}, { a: 3 })
console.log("a:", a)
let Father = function () {
this.lastName = "liu"
this.country = "China"
}
let Children = function () { }
Children.prototype = new Father()
let f = new Father()
let c = new Children()
console.log("f", JSON.stringify(f))
console.log("c", JSON.stringify(c))
let f1 = JSON.parse(JSON.stringify(f))
let c1 = JSON.parse(JSON.stringify(c))
console.log("f1", f1.lastName) // liu
console.log("c1", c1.lastName) // undefined
let r1 = Object.assign(f, { dd: 34 })
console.log("r1:", r1)
console.log(r1.lastName) //liu
let r2 = Object.assign(c, { dd: 33 })
console.log("r2:", r2)
console.log(r2.lastName) // liu
4、writable默认是false
let obj = { a: 333 }
console.log("obj:", obj.a) //333
obj.a = 444
console.log("obj", obj.a) //444
let obj2 = {}
Object.defineProperty(obj2, 'a', {
value: 333
})
console.log("obj2:", obj2.a) //333
obj2.a = 444
console.log("obj2:", obj2.a) //333
// 由此可以看出 Object.defineProperty默认的writable是false
5、get和set
- 有get和set,不能写 value、writable描述符
<!-- get和set方法理解 -->
let obj = {}
Object.defineProperty(obj, 'a', {
set(val) {
console.log("set a")
},
get() {
return 333
}
})
console.log(obj.a) //333
obj.a = 444 // set a
console.log(obj.a) //333
let obj = {}
Object.defineProperty(obj, 'a', {
// value: 333, // 有get和set,写value描述符会报错
// writable: true, // 有get和set,写writable描述符会报错
configurable: true,
enumerable: true,
get() {
return this.value
},
set(val) {
this.value = val
}
})
console.log(obj.a) // undefined
obj.a = 333
console.log(obj.a) // 333