Object.defineProperty()

 
 
 
对象的定义与赋值

经常使用的定义与赋值方法obj.prop =value或者obj['prop']=value

 

Object.defineProperty()语法说明

Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性

Object.defineProperty(obj, prop, desc)

  1. obj 需要定义属性的当前对象
  2. prop 当前需要定义的属性名
  3. desc 属性描述符

一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。

属性的特性以及内部属性

javacript 有三种类型的属性

  1. 命名数据属性:拥有一个确定的值的属性。这也是最常见的属性
  2. 命名访问器属性:通过gettersetter进行读取和赋值的属性
  3. 内部属性:由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 = '数据变了';
            }


原文地址:https://www.cnblogs.com/jcxfighting/p/12061589.html