Object.defineproperty实现数据和视图的联动

Object.defineproperty语法

在一个对象上定义新的属性


var o = {}; // 创建一个新对象

// Example of an object property added with defineProperty with a data property descriptor

Object.defineProperty(o, "a", {value : 37,

                               writable : true,

                               enumerable : true,

                               configurable : true});

// 对象o拥有了属性a,值为37


// Example of an object property added with defineProperty with an accessor property descriptor

var bValue;

Object.defineProperty(o, "b", {get : function(){ return bValue; },

                               set : function(newValue){ bValue = newValue; },

                               enumerable : true,

                               configurable : true});

o.b = 38;


数据和视图联动

给对象o定义新的属性b,并且定义属性b的get和set方法,当o.b的时候会调用b属性的get方法,给b属性赋值的时候,会调用set方法,这就是修改数据的时候,视图会自动更新的关键

前端获取数据后,需要根据数据操作dom,视图变化后,需要修改不少代码,有没有方法将数据和dom操作隔离,看一个例子

显示用户信息的html模版

<div>

    <p>你好,<span id='nickName'></span></p>

    <div id="introduce"></div>

</div>      

 


//视图控制器

var userInfo = {};

Object.defineProperty(userInfo, "nickName", {

    get: function(){

        return document.getElementById('nickName').innerHTML;

    },

    set: function(nick){

        document.getElementById('nickName').innerHTML = nick;

    }

});

Object.defineProperty(userInfo, "introduce", {

    get: function(){

        return document.getElementById('introduce').innerHTML;

    },

    set: function(introduce){

        document.getElementById('introduce').innerHTML = introduce;

    }

})


 

//数据

//todo 获取用户信息的代码

....


userInfo.nickName = "xxx";

userInfo.introduce = "我是xxx,我来自云南,..."

 

设置userInfo的nickName属性时会调用set方法,更新dom节点的html

移动端兼容性

Feature

Firefox Mobile (Gecko)

Android

IE Mobile

Opera Mobile

Safari Mobile

Basic support

4.0 (2)

(Yes)

?

11.50

(Yes)

参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Javascript作为一种语言,有个美誉,开发者可以重新定义任何事情。虽然这在过去的一些javascript可以,但是ECMAScript5中已经开始得到改变,例如,我们可以使用Object.defineProperty创建一个不能被修改的对象的属性。本文中我们将讲述Object.defineProperty的基本用法。 如果你想在文章开始之前,深入了解Object.defineProperty方法,请戳。

 

一、基本用法

假如我想构建一个math.js库,看下面的实例:

 

 

var mathObj = {

    constants: {

        "pi": 3.14

    },

    areaOfCircle: function(radius) {

        return this.constants.pi*radius*radius;

    }

在上例中,如果有人改变pi的值,那么我们将不会得到正确的计算结果,虽然有很多方法可以解决此问题,但是最简单的方法是使用pi属性不可写。看下面实例:

 

 

var mathObj = {

    constants: {},

    areaOfCircle: function(radius) {

        return this.constants.pi*radius*radius;

    }

 

Object.defineProperty(mathObj.constants, "pi", {

    value: 3.14,

    writable: false

});

 

mathObj.constants.pi = "Benjamin";

 

//Outputs: 3.14

console.log(mathObj.constants.pi);

Object.defineProperty(obj, prop, descriptor)方法接收三个参数:需要添加或修改属性的对象,属性名称,属性描述options。从上例可以看出,当给pi赋值为“Benjamin”时,最后输出的值还是3.14。 但是如果给math.js使用“use strict",将会报错,和给undefined赋值一样:

 

 

"use strict";

var mathObj = {

    constants: {},

    areaOfCircle: function(radius) {

        return this.constants.pi*radius*radius;

    }

 

Object.defineProperty(mathObj.constants, "pi", {

    value: 3.14,

    writable: false

});

 

mathObj.constants.pi = "Benjamin";

 

//<span style="color: #ff0000;">Outputs: Uncaught TypeError: Cannot assign to read only property 'pi' of #<Object></span> 

console.log(mathObj.constants.pi);

第三个参数的options中,writable默认值为false,所以在上例中可以省略,configurable默认值为false,如果你想使用你的库的用户故意重写pi的值,你可以设置configurable值为true。

 

 

Object.defineProperty(principia.constants, "pi", {

    value: 3.14,

    configurable: true

});

但是当你使用Object.defineProperty时,也有一种相当大的Hack,即使设置了writable的值,它也不会保持属性值不变的:

 

 

var container = {};

 

Object.defineProperty(container, "arr", {

    writable: false,

    value: ["a", "b"]

});

 

container.arr = ["new array"];

 

// Outputs: ["a", "b"]

console.log(container.arr);

 

container.arr.push("new value");

 

// Outputs: ["a", "b", "new value"]

console.log(container.arr);

arr数组是不可写的,所以始终指向同一个数组,但是数组的成员是可以变化的,所以将来可能会增加锁定数组或者对象来解决此问题。

 

二、兼容性

因为Object.defineProperty方法是ES5的一部分,所以在IE9及现代浏览器,IE8中只得到了部分实现,尽可以使用在DOM对象上,不幸的是,并没有IE8相关的shim来兼容。但是,如果你不需要处理旧的浏览器,defineProperty可能会有你使用的地方。 以上就是对Object.defineProperty方法的描述,文中不妥之处,还望批评指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值