Object.defineProperty 的基础知识

2020-04-20  本文已影响0人  头发飘逸

Object.defineProperty 这个方法大家耳熟能详,可以对 对象的属性进行添加或修改的操作。即可以进行 数据劫持 。vue就是通过这个方法来劫持数据的,进而实现数据的双向绑定

方法说明:

用来定义或修改对象的属性。

共3个参数都是必须的:obj-目标对象、newKey-属性名、{}-属性特性

给对象的属性添加特性描述(第三个参数),目前提供两种形式:数据描述和存取器描述。

数据描述:
Object.defineProperty(obj,"newKey",{
  value:"hello", // 设置属性的值
  writable:false, // 值是否可以重写。true | false
  enumerable:false, // 目标属性是否可以被枚举。true | false(使用for...in或Object.keys())
  configurable:false // 目标属性是否可以被删除或是否可以再次修改特性 true | false
});
存取器描述:

注:当使用了getter或setter方法,不允许使用writable和value这两个属性

var obj = {};
var initValue = 'hello';
Object.defineProperty(obj,"newKey",{
    get:function (){
        //当获取值的时候触发的函数
        return initValue;    
    },
    set:function (value){
        //当设置值的时候触发的函数,设置的新值通过参数value拿到
        initValue = value;
    }
});
//获取值
console.log( obj.newKey );  //hello

//设置值
obj.newKey = 'change value';

console.log( obj.newKey ); //change value
下面我来通过Object.defineProperty 实现简单的数据双向绑定
<body>
    <div id="app">
    <input type="text" id="txt">
    <p id="show"></p>
</div>
</body>
<script type="text/javascript">
    var obj = {}
    Object.defineProperty(obj, 'txt', {
        get: function () {
            return obj
        },
        set: function (newValue) {
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.addEventListener('keyup', function (e) {
        obj.txt = e.target.value
    })
</script>

好了,这样就实现了间的数据双向绑定

来说下Object.defineProperty的缺点:

1.无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。所以vue才设置了7个变异数组(push、pop、shift、unshift、splice、sort、reverse)的 hack 方法来解决问题。

2.只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。如果能直接劫持一个对象,就不需要递归 + 遍历了。所以 vue3.0 会使用 Proxy 来替代Object.defineProperty

Proxy:代理

听说vue3.0 会用 proxy 替代 Object.defineProperty()方法。所以预先了解一些用法是有必要的。

proxy 能够直接 劫持整个对象,而不是对象的属性,并且劫持的方法有多种。而且最后会返回劫持后的新对象。所以相对来讲,这个方法还是挺好用的。不过兼容性不太好。

关于proxy的介绍与用法,可以看看 阮一峰老师的 这篇文章

上一篇 下一篇

猜你喜欢

热点阅读