博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对javscript中Object.defineProperty的理解
阅读量:6501 次
发布时间:2019-06-24

本文共 2806 字,大约阅读时间需要 9 分钟。

  自己在使用vue的过程中经常会用到听到数据双向绑定这个词,而且我们还可以直接通过调用this.msg(this表示vue实例),来获取data上的数据,以前一直不太明白为什么可以这样获取,直到有一天我在论坛里看到了寻找海蓝96这位大佬写的文章,才明白其原理,所以在此记录一下。

1、Object.defineProperty(obj,key,descriptor)

  Object.defineProperty主要是通过Get和Set这两个访问器属性来实现数据双向绑定的。说到这里必须先介绍以下js对象的两种特性。 ECMAScript中有两种属性:数据属性和访问器属性。这是js中任何对象都拥有的特性。

数据属性主要是用于对数据的描述。数据属性主要有以下4个特性。

1、Configurable:(字面意思是可配置的,我理解为可操作(删除、修改))表示能否通过delete操作来删除属性,以及能否修改属性,或者能否将属性修改为访问器属性。直接定义在对象上的属性,该特性值默认为true。
2、Enumerable:字面意思是可枚举的,表示能否通过for-in循环来遍历属性。直接在对象上定义的属性,该特性值默认为true。
3、Writable:表示能否修改属性的值。直接定义在对象上的该特性值默认也为true。
4、Value:这个特性包含着属性的数据值。对对象属性的读写操作都是在这个特性上。该特性的默认值为undefined。

  想要修改上面的4个特性就得调用Object.defineProperty(obj,key,descriptor)方法,descriptor表示的是一个对象,对象中的属性必须是这四个特性中的一项或多项。

注意: 1、多次调用Object.defineProperty()方法修改同一个属性,只要把configurable特性设置为false后,就不能再把它变成可配置的了(再次调用Object.defineProperty()将configurable特性设置为true会报错),即这个过程是不可逆的,不能再对对象属性进行delete操作,但是还可以对对象属性进行修改操作。

Object.defineProperty(obj,"name",{    configurable:false,    enumerable:true,    writable:true,    value:"james"});delete obj.name;console.log(obj);//{name: "james"},可见不能对obj进行删除操作了。obj.name="test";console.log(obj.name);//test 还是可以对属性进行修改复制代码

2、调用Object.defineProperty()方法时,如果不指定Configurable、Enumerable和writable等特性的值,默认为false。

访问器属性也有4个。但是不包含数据值

1、Configurable:(字面意思是可配置的,我理解为可操作(删除、修改))表示能否通过delete操作来删除属性,以及能否修改属性,或者能否将属性修改为访问器属性。直接定义在对象上的属性,该特性值默认为true。
2、Enumerable:字面意思是可枚举的,表示能否通过for-in循环来遍历属性。直接在对象上定义的属性,该特性值默认为true。
3、Get:在读取属性时调用的函数。 默认值为undefined。
4、Set:在写入属性时调用的函数。的默认值为undefined。

注意:不能使用Object.defineProperty()方法同时修改默认数据属性和访问器属性。即set和get访问器属性不能与writable以及value特性共存。

Object.defineProperty(obj,"name",{    configurable:true,    enumerable:true,    writable:true,    value:"james",    get(){        return this.val;    },    set(newVal){        this.val=newval;    }});//Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #复制代码

  个人觉得数据属性和访问器属性的Configurable和Enumerable没什么区别。访问器属性主要用的是Get和Set这两个。

可以通过Object.defineProperty()实现简单的数据双向绑定。实现代码如下:

//通过操作可以发现,在test1中输入会改变test2中的值,在test2中输入也能改变test1中的值。复制代码

vue中为什么可以直接通过this.msg获取到data中的msg,原理代码如下:

class Vue{        constructor(options={}){            this.$options=options;            this._data=options.data;            let data=this._data;            Object.keys(data).forEach((key)=>{                this._proxy(key)            })        };        _proxy(key){            //以this做为obj,将data对象上的属性全部绑定到vue实例上来            Object.defineProperty(this,key,{                configurable:true,                enumerable:true,                get(){                    return this._data[key];                },                set(newval){                    this._data[key]=newval;                }            })        }    }复制代码

转载于:https://juejin.im/post/5cfcf9806fb9a07ec27b96aa

你可能感兴趣的文章
oracle
查看>>
redis使用过程中主机内核层面的一些优化
查看>>
我也要谈谈大型网站架构之系列(2)——纵观历史演变(下)
查看>>
大话设计模式(Golang) 二、策略模式
查看>>
使用PostgreSQL 9.6 架设mediawiki服务器
查看>>
数据库服务器硬件对性能的影响
查看>>
LVM
查看>>
windows+群辉服务器环境下,搭建git版本管理
查看>>
Ubuntu 修改源
查看>>
php 几个比较实用的函数
查看>>
(译)OpenGL ES2.0 – Iphone开发指引
查看>>
@RestController 与 @RequestMapping
查看>>
黑马程序员.bobo.DAY.1
查看>>
Unity shader 官网文档全方位学习(二)
查看>>
pbrun
查看>>
浏览器加载和渲染网页顺序
查看>>
深入剖析Android系统试读样章
查看>>
测试用例出错重跑--flaky插件
查看>>
yaf的安装
查看>>
比较java与C++的不同
查看>>