Vuejs让前端飞

实现 MVVM (一)- Object.definePrope

2018-10-10  本文已影响12人  passMaker

动机 (写在前面)

之前在学习构建自己轮子组件库时,被反复的提到了 MVVM 核心实现方法的问题,其中包括 Vuejs 的原理。逛过一些技术社区。一些前辈和大佬给出了建议。初级水平的人并不推荐去看 Vuejs 的源码,截止到今天,Vuejs 2.5.17 版本的源码高达 10978 行。因此初级水平的人看源码性价比也许真的并不高。一些前辈和大牛给出的建议是,Vuejs 的实现原理尤雨溪已经说得很明白了。建议大家可以使用自己的方式去简单模拟一下 MVVM 的思想,也许可能实现得并不优雅。但这样做比头铁的看源码来得更有价值和意义。

本文是我通过已经知晓的 Vuejs 实现原理来简单实现 MVVM 的系列博文的第一篇,主要总结归纳了 Object.defineProperty() 的方法特性。

Object.defineProperty

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。其语法是:

Object.defineProperty(obj, prop, descriptor)

参数说明(三个参数都是必须的):

obj   // 要在其上定义属性的对象。
prop   // 要定义或修改的属性的名称。
descriptor   // 将被定义或修改的属性描述符。

返回值为传入参数的对象,即第一个参数 obj

使用方法

以下三种方法都可以用来定义/修改一个对象属性,其中包含 Object.defineProperty() 方法。

var obj = {}
obj.name = 'evenyao'
obj['age'] = 27
Object.defineProperty(obj, 'intro', {
    value : 'hello world'
})

console.log(obj)  // {name: 'evenyao', age: 27, intro: 'hello world'}

configurable

configurable 是该方法传参中最后一项 descriptor 中的属性描述符。configurable 的值设置为 false 后(如果没设置,默认就是 false)。以后就不能再次通过 Object.defineProperty() 方法修改属性,也无法删除该属性。如果configurable 的值设置为 true 后,能删除该属性,但也不能修改。

举例说明:

var obj = {}
Object.defineProperty(obj, 'intro', {
    configurable: false,
    value : 'hello world'
})
obj.intro = 'i wanna change it'
console.log(obj.intro)   // "hello world"
delete obj.intro           // false, 删除失败
console.log(obj.intro)  // "hello world" 

Object.defineProperty(obj, 'name', {
    configurable: true,
    value : 'i wanna change it'
})
delete obj.intro   // true  , 成功删除

enumerable

enumerable 也是该方法传参中最后一项 descriptor 中的属性描述符。设置 enumerable 属性为false 后,遍历对象的时候会忽略当前属性(如果未设置,默认就是 false 不可遍历)。

举例说明:

var obj = {name: 'evenyao'}
Object.defineProperty(obj, 'age', {
    enumerable: false,
    value: 27
})

for(var key in obj){
    console.log(key)   // 只输出 'name', 不输出'age'
}

value 和 writable

valuewritable数据描述符,具有以下可选键值:

举例说明:

var obj = {name: 'evenyao'}
Object.defineProperty(obj, 'age', {
    value: 27,
    writable: false
})

obj.age = 26
console.log(obj.age)   // 27, writable为 false 时,修改对象的当前属性值无效

区别

configurable: truewriable: true 的区别是,前者是设置属性能删除,后者是设置属性能修改

get 和 set

getset存取描述符,有以下可选键值:

var obj = {}
var age 
Object.defineProperty(obj, 'age', {
    get: function(){
        console.log('get age...')
        return age
    },
    set: function(val){
        console.log('set age...')
        age = val
    }
})

obj.age = 100  // 'set age...'
console.log(obj.age) // 'get age...', 100



值得一提的是这个案例和之前我在 从「闭包」到 思考人生 那篇文章里面封装的那个闭包函数(中文的案例2)是很相似的。事实上在我看来,他们所达到的效果是一样的。

var Age = (function(){
  var age = undefined
  function set(s){
    age = s
    console.log('set age...')
  }
  function get(){
    console.log('get age...')
    return age 
  }
  return {
    set: set,
    get: get
  }
})()

Age.set(100)  // 'set age...'
Age.get()  // 100



数据描述符存取描述符 是不能同时存在的。如果同时存在,代码就会报错。

例如下面例子,就是不被允许的。这段代码同时出现了 valueget/ set。所以会报错。

var obj = {}
var age 
Object.defineProperty(obj, 'age', {
    value: 27,
    get: function(){
        console.log('get age...')
        return age
    },
    set: function(val){
        console.log('set age...')
        age = val
    }
})
上一篇下一篇

猜你喜欢

热点阅读