对一个对象的属性进行修改或者新建
语法:Object.defineProperty(obj, prop, descriptor)
入参说明:对象名称、属性名、属性描述
let object1 = {}
// 已下两种写法相等
Object.defineProperty(object1, "name", {value: "kangkang"}
Object.defineProperty(object1, "name", {
value: "kangkang",
configurable: false, // 该属性的描述符是否能够被改变,默认false
enumerable: false, // 该属性是否能被遍历到,默认false
writable: false // 该属性的值是否能被修改, 默认false
})
// 已下两种写法相等
object1.name = "kangkang"
Object.defineProperty(object1, "name", {
value: "kangkang",
configurable: true,
enumerable: true,
writable: true
})
以上之外,还有get 和 set 方法
注:描述符分数据描述符和存储描述符;两种描述符无法共存:
数据描述符可选键值:configurable enumerable writable value
存储描述符可选键值: configurable enumerable get set
即:value、writable和get、set无法共存,会报异常
当该对象获取改属性值或者修改该属性值是被调用:
let obj2 = {}
obj2.name = "kangkang"
Object.defineProperty(obj2, "name", {
enumerable: true,
configurable: true,
get () {
console.log('get')
},
set (newname) {
console.log('set', newname)
}
})
obj2.name // get
obj2.name = "Mike" // set Mike
vue项目数据劫持功能:
转载:https://www.cnblogs.com/zhangym118/p/8717999.html
关于对象的数据劫持:
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: Function
) {
const dep = new Dep()//创建订阅对象
const property = Object.getOwnPropertyDescriptor(obj, key)//获取obj对象的key属性的描述
//属性的描述特性里面如果configurable为false则属性的任何修改将无效
if (property && property.configurable === false) {
return
}
// cater for pre-defined getter/setters
const getter = property && property.get
const setter = property && property.set
let childOb = observe(val)//创建一个观察者对象
Object.defineProperty(obj, key, {
enumerable: true,//可枚举
configurable: true,//可修改
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val//先调用默认的get方法取值
//这里就劫持了get方法,也是作者一个巧妙设计,在创建watcher实例的时候,通过调用对象的get方法往订阅器dep上添加这个创建的watcher实例
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
}
if (Array.isArray(value)) {
dependArray(value)
}
}
return value//返回属性值
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val//先取旧值
if (newVal === value) {
return
}
//这个是用来判断生产环境的,可以无视
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = observe(newVal)//继续监听新的属性值
dep.notify()//这个是真正劫持的目的,要对订阅者发通知了
}
})
}
获取指定对象上一个自有属性对应的属性描述符
const obj = { a: 4 };
const descriptor = Object.getOwnPropertyDescriptor(obj, 'a');
console.log(descriptor.configurable); // true
console.log(descriptor.value); // 42
console.log(descriptor.get); // undefined
const descriptor = Object.getOwnPropertyDescriptors(obj);
console.log(descriptor); // Object { a: Object { value: 4, writable: true, enumerable: true, configurable: true } }
console.log(descriptor.a); // Object { value: 4, writable: true, enumerable: true, configurable: true }
将obj2中可枚举的属性值转移到obj1中,如果obj1、obj2中有属性的key相同,则obj2中的属性值会进行覆盖。
返回新的obj1
注: 用Object.assign({}, obj) 拷贝对象,如果只有一层,可以作为深拷贝
const obj1= { a: 1, b: 2 };
const obj2= { b: 4, c: 5 };
const objNew= Object.assign(obj1, obj2);
console.log(obj1);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(objNew);
// expected output: Object { a: 1, b: 4, c: 5 }
Object.keys()
Object.entries()返回一个给定对象自身可枚举属性的键值对数组;可用for循环进行遍历获取
const object1 = {
a: 'somestring',
b: 42,
c: 12
};
Object.keys(object1).forEach(item => {
console.log(item, object1[item]) // "a" "somestring"
})
Object.entries(object1).forEach(item => {
console.log(item, item[0]) // ["a", "somestring"] "a"
})