目录
第二章 - 03: 前端 进阶技巧之高阶函数
一, 防篡改对象
1-1:Configurable 和 Writable
- 1-2:Enumerable
- 1-3:get ,set
2-1: 不可扩展对象
2-2: 密封的对象
2-3: 冻结的对象
二, 自定义事件
第二章 - 03: 前端 进阶技巧之高阶函数
一, 防篡改对象
JavaScript 共享的本质一直是开发人员心头的痛, 因为任何对象都可以被在同一个环境中运行的代码修改.
ECMAScript5 致力于解决这个问题, 可以让开发人员定义防篡改对象(tamper-proof object). 它的原理就是
通过设置每个对象的属性的一下的默认属性:
[[Configurable]] --- 是否可配置
[[Writable]] --- 是否可以重新赋值
[[Enumerable]] --- 是否可列举的
[[Value]] --- 默认值
[[Get]]
[[Set]]
1-1:Configurable 和 Writable
下面我们就针对以上每一个属性进行 解析一下:
- // Demo one
- var o = {}
- Object.defineProperty(o, 'name', {
- value: 'zhang',
- configurable: false
- })
- console.log(o)
- Object.defineProperty(o, 'name', {
- writable: false
- })
- o.name = 'Li'
- console.log(o) // {name: 'zhange'} 属性未被改变
上面的 Demo 中 我们将 configurable 属性设置成为 false, 再对比下面的 Demo 来看 configurable 属性作用
- // Demo two
- var o = {}
- Object.defineProperty(o, 'name', {
- value: 'zhang',
- configurable: false
- })
- console.log(o)
- Object.defineProperty(o, 'name', {
- writable: true
- })
- o.name = 'Li'
- // Uncaught TypeError: Cannot redefine property: name 报错
总结: 当 [[Configurable]] 为 fasle 的时候 [[Writable]] 默认已经被设置 false, 如果去修改 [[Writable]] 的时候
则会报错. 那么我们就可以理解为 当 [[Configurable]] 为 false 的时候, [[Writable]] 是只能为 false 的.
1-2:Enumerable
我们还是用 Demo 来进行对比解释:
- var o = {}
- Object.defineProperty(o, 'age', {
- enumerable: true,
- value: 18
- })
- for(item in o) {
- console.log(item, o[item]) // age 18
- }
把 enumerable 设置成 false
- var o = {}
- Object.defineProperty(o, 'age', {
- enumerable: false,
- value: 19
- })
- for(item in o) {
- console.log(item, o[item]) // undefined
- }
- 1-3:get ,set
get 和 set 这对双胞胎我们已经说过多次了. 这次我们仔细来看下这个~
- var o = {}
- var v = 'coder'
- Object.defineProperty(o, 'job', {
- get: function() {
- console.log('get:', v)
- return v
- },
- set: function(newV) {
- console.log('set:', newV)
- v = newV
- }
- })
- o.job = 'xxx' // set: xxx
- // 很奇怪的一点就是 当我们在 浏览器控制台点开 o 对象的时候, 再次去点击 job 属性, 就会触发 get 方法.
2-1: 不可扩展对象
Object.preventExtensions(o)
可以使得 不能再给对象添加属性和方法
- var o = {name: 'zhang'}
- Object.preventExtensions(o)
- o.age = '12'
- console.log(o) // {name: 'zhang'}
- // 已经阻止了给对象添加属性和方法了. 再去添加 也未能添加上
- Object.isExtensible(o)
确定对象是否可以扩展
- var o = {name: 'zhang'}
- var res1 = Object.isExtensible(o)
- Object.preventExtensions(o)
- var res2 = Object.isExtensible(o)
- console.log(res1, res2) // true false
2-2: 密封的对象
Object.seal(o)
密封对象不可扩展, 而且已有成员的 [[Configurable]] 特性被设置为 false, 意味着不能删除属性和方法. 不可增加, 不能删除.
- var o = {name: 'Li'}
- Object.isSealed(o) // false
- Object.seal(o)
- Object.isSealed(o) // true
- Object.isSealed(o)
检测时候被密封了( )
2-3: 冻结的对象
Object.freeze(o)
最严格的防篡改级别就是冻结对象 (frozen object). 冻结的对象不能扩展, 又是密封的, 而且对象属性的[[Writable]] 特性会被设置为 false.
如果定义了 [[Set]] 函数, 访问器属性仍然是可写的.
- var obj = {age: 123}
- Object.freeze(obj)
- Object.isFrozen(obj) // true
- Object.isSealed(obj) // true
- Object.isExtensible(obj) // false
- Object.isFrozen(o)
检查是否被冻结
二, 自定义事件
基于 观察者模式的一种创建松散耦合代码的技术. 使用自定义事件有助于解耦相关对象, 保持功能的隔绝.
- function EventTarget(){
- this.handlers = {};
- }
- EventTarget.prototype = {
- constructor : EventTraget,
- addHandler : function(type,handler){
- if(typeof this.handlers[type] === 'undefined'){
- this.handlers[type] = [];
- }
- this.handlers[type].push(handler);
- },
- fire : function(event){
- if(!event.target){
- event.target = this;
- }
- if(this.handlers[type] instanceof Array){
- var handlers = this.handlers[event.type];
- for(var i = 0,len = handlers.length; i < len; i++){
- handlers[i](event);// 执行回调函数
- }
- }
- },
- removeHandler : function(type,handler){
- if(this.handlers[type] instanceof Array){
- var handlers = this.handlers[type];
- for(var i = 0,len = handlers.length; i < len; i++){
- if(handlers[i] === handler){
- break;
- }
- }
- handlers.splice(i,1);// 删除
- }
- }
- }
总结: 以上则为高阶函数中的相关的一些场景的应用, 但是这也仅仅是属于基础部分, 实际的使用场景还需要大家自己灵活处理.
好了, 本期这篇 blog 就先写到这里.
来源: https://www.cnblogs.com/erbingbing/p/9621339.html