对象的定义与赋值
经常使用的定义与赋值方法obj.prop =value
或者obj['prop']=value
Object.defineProperty()语法说明
Object.defineProperty()
的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
Object.defineProperty(obj, prop, desc)
- obj 需要定义属性的当前对象
- prop 当前需要定义的属性名
- desc 属性描述符
一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。
属性的特性以及内部属性
javacript 有三种类型的属性
- 命名数据属性:拥有一个确定的值的属性。这也是最常见的属性
- 命名访问器属性:通过
getter
和setter
进行读取和赋值的属性 - 内部属性:由JavaScript引擎内部使用的属性,不能通过JavaScript代码直接访问到,不过可以通过一些方法间接的读取和设置。比如,每个对象都有一个内部属性
[[Prototype]]
,你不能直接访问这个属性,但可以通过Object.getPrototypeOf()
方法间接的读取到它的值。虽然内部属性通常用一个双吕括号包围的名称来表示,但实际上这并不是它们的名字,它们是一种抽象操作,是不可见的,根本没有上面两种属性有的那种字符串类型的属性
obj: 待修改的对象
prop: 待修改对象的key
descriptor: 对象
{
configurable: 是否可配置的,true,可删除属性,可重新定义属性
enumerable: 是否可被枚举,默认是false, true,可以遍历
value: 待修改的key的value值
writable: 是否可重写,默认是false, true,可重新定义属性,不可删除属性
}
configurable:true,
var data = { title: '新闻', } // 给对象设置新的属性值 Object.defineProperty(data,'miaov',{ value: 'ketang', configurable: true, // 可配置的 }) console.log(data); // obj: {title: '新闻', miaov: 'ketang'} // configurable: true表示可配置的,可重新定义 Object.defineProperty(data,'miaov',{ value: '可重新配置', configurable: true, // 可配置的 }) data.miaov = '重新赋值' // 不可重写 delete data.miaov // 可删除属性 console.log(data); // obj: {title: '新闻', miaov: '可重新配置'}
configurable: false,
// 1. 给对象设置新的属性值 Object.defineProperty(data,'miaov',{ value: 'ketang', configurable: false, }) console.log(data); // obj: {title: '新闻', miaov: 'ketang'} // configurable: false表示不可配置的 报错 // Object.defineProperty(data,'miaov',{ // value: '不可重新配置', // }) data.miaov = '重新赋值' // 不可重写 delete data.miaov // 不可删除属性 console.log(data); // obj: {title: '新闻', miaov: '可重新配置'}
writable: true
// 1. 给对象设置新的属性值 Object.defineProperty(data,'miaov',{ value: 'ketang', configurable: false, writable: true, }) console.log(data); // obj: {title: '新闻', miaov: 'ketang'} // writable: true data.miaov = '重新赋值' // 可重写 delete data.miaov // 不可删除属性 console.log(data); // obj: {title: '新闻', miaov: '重新赋值'}
writable: false
// 1. 给对象设置新的属性值 Object.defineProperty(data,'miaov',{ value: 'ketang', configurable: false, writable: false, }) console.log(data); // obj: {title: '新闻', miaov: 'ketang'} // writable: false data.miaov = '重新赋值' // 不可重写 delete data.miaov // 不可删除属性 console.log(data); // obj: {title: '新闻', miaov: 'ketang'}
enumerable: true
var data = { title: '新闻' } Object.defineProperty(data,'miaov',{ configurable: true, value: '重新定义了', enumerable: true, // 可被枚举,被循环 }) for(var attr in data){ console.log(attr); // title、miaov }
enumerable: false
var data = { title: '新闻' } Object.defineProperty(data,'miaov',{ configurable: false, value: '重新定义了', enumerable: true, // 可被枚举,被循环 }) for(var attr in data){ console.log(attr); // title }
get / set
var data = { title: '新闻' } var val = '新的值' Object.defineProperty(data,'title', { get(){ // 访问数据的时候会触发 console.log('我访问数据了'); return val }, set(newValue){ // 设置新值的时候会触发 console.log('我设置了新值'); console.log(newValue); val = newValue; } }) console.log( data.title ); // 我访问数据了 新的值 data.title = '123'; // 相当于对属性重新赋值 // 我设置了新值 123 console.log(data.title); // 我访问数据了 123
模拟数据劫持
var data = { title: '新闻', miaov:1 } // 数据劫持,转成getter和setter observer(data) function observer(obj){ Object.keys(obj).forEach((item) => { defineReactive(obj,item,obj[item]) }) } function defineReactive(obj,key,value){ Object.defineProperty(obj,key, { get(){ return value; }, set(newValue){ value = newValue; title.innerHTML = newValue ; } }) } console.log(data); var title = document.getElementById('title'); var btn = document.getElementById('btn'); title.innerHTML = data.title; btn.onclick = function (){ data.title = '数据变了'; }