JavaScript:保护对象

默认的情况下,js的所有对象都是可以扩展的,也就是说,任何时候都可以向对象中添加属性和方法。在开发过程中,很可能会意外的修改别人的代码,因此,需要将不让修改的对象保护起来。

保护对象: 阻止程序对一个对象执行不合理的修改
两个层面的保护:

一. 保护单个属性: 阻止对对象中某个属性执行不合常理的修改

1、ES3和ES5中主要通过闭包来对属性进行保护

function  () {
    var data = {
        name : '张三',
        sex: 'man',
        age: 18
    }
    // 向外部暴露可以访问内部属性的方法
    this.get = function (key) {
        return data[key]
    }
    this.set = function (key, value) {
        if(key != 'sex') { // 对需要保护的属性设置不可更改
            data[key] = value
        }
    }
}

2、ES5还可以通过Object.defineProperty来通过修改属性默认特性来保护属性

Object.defineProperty(Person, 'sex', {
    value: //实际存储属性值
    writable: true/false, //是否可以修改 默认是true
    enumerable: true/false, //是否可被for in遍历 仅仅只能控制 for in 无法控制访问
    configurable: true/false, //是否可修改其他属性特征 是否可删除该属性
}

3、ES6可以通过 Proxy 来保护对象

let Person = {
    name: 'ES6',
    age: 15,
    sex: 'male'
}
// 使用代理对原对象进行封装,生成特殊的代理对象
// 代理对象成为了代码交互的主要对象,而实际目标对象处于被保护的状态
let person = new Proxy(Person, {
    get (target, key) {
        return target[key]
    },
    set (target, key, value) {
        if(key != 'sex') {
            target[key] = value
        }
    }
})
二. 保护对象结构: 阻止乱添加删除属性

1、不可扩展,即禁止给对象添加新属性和方法:Object.preventExtensions(对象);

	var student = { name: "王五" };
	Object.preventExtensions(student);
	student.age = 26;
	alert(student.age); //undefined

在非严格模式下,给对象添加新成员会导致静默失败,因此student.age 将是 undefined。
在严格模式下,尝试给不可扩展的对象添加新成员会导致抛出错误。虽然不能给对象添加新成员,但已有的成员则丝毫不受影响。已有的成员仍然可以修改和删除。使用 Object.istExtensible()方法可以确定对象是否可以扩展。

	var student = { name: "王五" };
	alert(Object.isExtensible(student)); //true
	Object.preventExtensions(student);
	alert(Object.isExtensible(student)); //false

2、禁止添加、删除属性和方法,属性值可以修改(密封对象):使用Object.seal()方法。

	var student = { name: "王五" };
	Object.seal(student);
	student.age = 26;
	alert(student.age); //undefined
	delete student.name;
	alert(student.name); //"王五"

上面的代码执行过程中,添加 age 属性的行为被忽略了。而删除 name 属性的操作也被忽略了,因此这个属性没有受任何影响。这是在非严格模式下的行为。在严格模式下,尝试添加或删除对象成员都会导致抛出错误。
使用 Object.isSealed()方法可以确定对象是否被密封了。因为被密封的对象不可扩展,所以用Object.isExtensible()检测密封的对象也会返回 false。

3、不可拓展、密封且不可修改(冻结对象),ES5的Object.freeze()方法可以用来冻结对象。
  冻结对象数据属性的Writable特性会被设置为 false。由于访问器属性没有writable,所以访问器属性还是可以用的。

	var student = { name: "王五" };
	Object.freeze(student);
	student.age = 26;
	alert(student.age); //undefined
	delete student.name;
	alert(student.name); //"王五"
	student.name = "李四";
	alert(student.name); //"王五"

与不可拓展和密封一样,在非严格模式下对冻结的对象执行非法操作会被忽略,而在严格模式下会抛出错误。
可以使用 Object.isFrozen()方法用于检测冻结对象。因为冻结对象既是密封的又是不可扩展的,所以用 Object.isExtensible()和 Object.isSealed()检测冻结对象将分别返回 false和 true。

var student = { name: "王五" };
alert(Object.isExtensible(student)); //true
alert(Object.isSealed(student)); //false
alert(Object.isFrozen(student)); //false
Object.freeze(student);
alert(Object.isExtensible(student)); //false
alert(Object.isSealed(student)); //true
alert(Object.isFrozen(student)); //true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值