amandakelake/blog

Object.defineProperty() 和双向绑定原理

amandakelake opened this issue · 0 comments

先简单看下MDN上的介绍
Object.defineProperty() - JavaScript | MDN

一、 Object.defineProperty(obj, prop, descriptor)

Obj:要在其上定义属性的对象
prop:要定义或修改的属性的名称
Descriptor:将被定义或修改的属性描述符,返回被传递给函数的对象

example

var obj = {};
Object.defineProperty(obj, 'name', {
    value: 'mike'
});

console.log(obj); // mike

ECMAScript有两种属性:数据属性和访问器属性

一、数据属性

1、 [configurable]

总开关,一旦为false,就不能再设置他的其他属性(value,writable,configurable)

2、[enumerable]

决定了能否被for(prop in obj)Object.keys()枚举

Object.defineProperty(dream, 'a', {
    value: 1,
    enumerable: false // 不可枚举
});
Object.defineProperty(dream, 'b', {
    value: 2,
    enumerable: true // 可枚举
});

// 只会输出 b
for(prop in dream) {
    console.log(prop);
}

3、[writable]

当且仅当仅当该属性的writabletrue时,该属性才能被赋值运算符改变,默认值为false

4、[Value]

valueget,set是不可以共存的,定义了value后就不能够再定义get,set特性了

二、访问器属性

访问器属性不包含数据值,没有[value]
它们包含一对儿getter和setter函数(但都不是必须的)

1、 [configurable]

同上

2、[enumerable]

同上

3、[Get]

读取属性时调用的函数,默认underfined

4、[Set]

写入属性时调用的函数,默认underfined

看个例子

let a = {};
Object.defineProperty(a, 'p', {
  get: () => {
    return 1
  },
  set: (newValue) => {
    console.log(newValue)
  }
})
a.p = 2;
console.log(a.p);

// 2
// 1

a定义了一个访问器属性p
a.p = 2时调用set方法,但这里什么都没做,只是打印了想要设置的值2

console.log(a.p);调用get方法,但也只是固定返回1而已

从这个简单的例子,相信你能举一反三

三、简易Vue双向绑定

看个最简单的vue例子,只是数据和dom节点的绑定

html

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

Js

//视图控制器
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;
    }
})

愉快地绑定数据交互

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