六月份学vue的时候,当时只知道它是双向绑定,数据改变,视图层也会改变;视图改变,数据也会改变。那个时候只求会用,不求甚解。接下来的一段时间内陆陆续续接触到关于双向绑定的知识,大概只知道好像与Object.defineProperty()有关。后面看到一本书JavaScript for php Developer,书上讲到了对象的属性是可以定义权限的,当时记得权限包括:可读可写可枚举等,印象深的记住了这几个,那个时候才知道对象的属性定义背后不简单,但是当时也并没有去深究与数据劫持的关系,只是大脑一直记得有这么个东西。
后来陆陆续续的又接触到一些零零碎碎的知识和概念,大脑对这些知识有了一些想法,然后就想自己再弄明白这些问题,这个时候自己对这些东西也不抗拒了,想知道什么叫数据劫持,与框架又有什么联系。
然后最近一直听说前端面试会面ES5实现const,当时我的想法就是使用对象的可读不可写权限,但搁置没有去实现细节。
这两天觉得可以去试试写一写。
ES5 const 实现:
ES5 const在全局作用域下定义的变量会挂在window中,并且没有块级作用域的实现(后面会讲)。
ES5 const通过函数来让一个变量或者属性挂在一个对象上。这里举例用的是window对象。
下面定义的是consts()函数,注意是consts,多了个s加以区分
function consts(variable,value){ //variable:变量名 value:变量值
// Object.defineProperty()有三个参数,第一个是要挂在哪个对象下面,第二个是属性名或变量名,第三个是一个对象,里面
// 是配置权限
Object.defineProperty(window,variable,{
get:function(){return value}, //在读取属性时调用的函数。默认值为undefined。
set:function(anotherVariable){ //在给属性赋值时调用的函数。默认值为undefined。anotherVariable是指给属性赋值
// 时的值
console.log(`anotherVariable:${anotherVariable};value:${value}`);
if(anotherVariable !== value){ //这里使用了闭包,value在这里使用,一直保存在内存中,没有被销毁,然后每
//次给属性赋值时会让传过来的值与value比较,用的是!==,如果是相等则表示第
//一次赋值,不相等则表示第二次赋值并报错
console.error(`${variable} is already assignmented.`);
}else{
return value;//第一次赋值则直接赋值
}
},
configurable:false, // 表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属
//性.默认值为true。
enumerable:false, 表示能否通过for-in循环返回属性。默认值为true.
})
}
consts('a',5);
console.log(a);
a=12;
前面说ES5没有块级作用域,然后现在实现的consts()也是如此,当你在一个函数里使用consts()时,因为consts()定义的变量或者说属性是挂在某个对象上的,所以在这个函数作用域外面也是可以访问这个属性的。但在es6中的const是由块级作用域的,在函数体内用const定义一个变量,外部一般来说是不能访问的(闭包除外)。
而当用consts()定义一个属性(变量),外部是可以访问的
vue双向数据绑定用到了文档碎片documentFragment、Object.defineProperty、proxy及发布订阅模式,这里就只解释了Object.defineProperty(),其它知识点后续深究。
上面对Object.defineProperty()有了大概的了解,可以思考一下它在框架中的运用,我一开始听到数据劫持是不明所以然的,但是明白了Object.defineProperty()的作用后,就大概明白为什么叫做数据劫持了。框架它要做的东西就是在get和set里面,当我们对一个对象的属性进行了改变,它会触发set,然后框架就会将数据的变化表现在视图上。里面框架做了非常多的东西,这里只是浅显地管中窥豹,专研一下很有趣。
个人见解,里面肯定有不足之处,欢迎讨论.