首页 > 技术文章 > 《前端之路》之 JavaScript 进阶技巧之高阶函数(下)

erbingbing 2018-09-10 17:44 原文

第二章 - 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)
检测时候被密封了(

推荐阅读