您的位置:首页 > Web前端 > JavaScript

【面向JS--ES5保护对象】

2017-10-14 11:07 232 查看

前言

你知道吗,对象的属性也是有属性的!

js中对象的普通属性,随时可别修改为任何值,随时可添加新属性,随时可被删除。

这是因为对象的属性默认是可操作的,而通过修改对象属性的属性,我们可以设置对象属性的可操作性。

我们设置的目的就是 保护对象保护属性

回顾Object.create():

基于一个父对象,创建一个子对象,并为子对象扩展新属性。
var son=Object.create(父对象,{
扩展属性名1:{
writable:true,//是否可修改,可以省略
value:属性值,
configurable:true//可以设置,可以省略
},
扩展属性名2:{...}
});


保护属性

属性分为:

命名属性: 可用.访问到的属性
数据属性: 直接存储属性值的属性


每个属性都有四大特性:

value: 实际存储属性值
writable: 是否可修改 默认为true
enumerable: 是否可被for in遍历到 默认true
仅能控制for in,无法控制.的访问
configurable: 是否可修改其它特性
是否可删除该属性


获取四大特性:

var attrs=Object.getOwnPropertyDescriptor(obj,"属性名");


设置四大特性:

Object.defineProperty(obj,"属性名",{
特性: 值,
})
问题: 一次只能修改一个属性的四大特性
解决: 同时修改多个属性的四大特性?
Object.defineProperties(obj,{
属性名:{ 特性: 值, ... },
... : ...
})


问题: 如果要修改的属性不存在?

答: 会自动创建该属性:
强调:
通过defineProperty添加的属性,四大特性默认都为false!
通过对象直接量添加的属性,四大特性默认值都是true!


问题: 四大特性,只能对属性提供基本的保护,如何使用自定义规则保护属性

访问器属性: 不直接存储属性值,专门对其它属性提供保护的特殊属性
为什么: 数据属性的四大特性无法使用自定义规则保护属性
何时: 只要使用自定义规则保护属性时
如何: 2步:
1、定义一个闭包结构,实际存储属性值
2、定义一个访问器属性来保护闭包中的局部变量,如下:


+function(){
var 变量;
Object.defineProperty(obj,"属性名",{
get:function(){
return变量;
},
set:function(val){
变量=val;
},
enumerable:true/false,
configurable:true/false
})
}();


//自定义特性,设置访问器属性
//匿名函数自调
var eric={id:1001,ename:"Eric"};
+function(){
var _age;
Object.defineProperty(eric,"age",{
get:function(){return _age;},//get(){},
set:function(val){
if(val>=18&&val<=65) _age=val;
else throw new Error("年龄介于18~65之间")
}
})
}();
eric.age=20;
console.dir(eric);
console.log(eric.age);


问题: 受保护的数据不能保存在普通的数据属性中

因为数据属性可随意被访问!
解决:
内部属性: 不允许用.访问的属性
比如: class  __proto__


保护对象

对整个对象提供保: 防篡改

三个级别:

1、防扩展: 禁止向对象中添加新属性

Object.preventExtensions(obj);


2、密封: 即防扩展,又禁止删除任何属性

Object.seal(obj);
2件事: 1、防扩展
2、将所有属性的configurable都设置为false!


3、冻结: 即防扩展,又禁止删除,同时禁止修改一切属性值

Object.freeze(obj);
3件事: 1、防扩展
2、将所有属性的configurable都设置为false!
3、将所有属性的writable都设置为false


//最严谨的构造函数,员工类型
function Emp(ename,id,salary,age){
this.ename=ename;
this.id=id;
this.salary=salary;
var _age;
Object.defineProperties(this,{
id:{writable:false},
salary:{enumerable:false},
age:{
set(val){
if(val>=18&&val<=65) _age=val;
else throw new Error("年龄介于18~65之间")
},
get(){return _age},
enumerable:true //这里注意
//用.创建的新属性,通过defineProperty/defineProperties修改,默认值为true
//用defineProperty/defineProperties添加的新属性,特性的默认值为false
}
})
this.age=age;
//防扩展:(禁止添加新属性)(extensible:false)
//设置当前新对象禁止扩展新属性
//Object.preventExtensions(this);
//密封,不可扩展,也不可删除(configurable:false)
Object.seal(this);
//冻结,密封且不可修改(wretable=false)
//Object.freeze(this);
}
var Lisi=new Emp("lisi",101,10000,24);
var Hanmei=new Emp("hanmei",102,13000,26);
var Zhaoyun=new Emp("zhaoyun",103,18000,29);
//Zhaoyun.age=78;//错误
for(var key in Zhaoyun)console.log(Zhaoyun[key]);
console.dir(Lisi);
console.dir(Hanmei);
console.dir(Zhaoyun);


严格模式

比普通的js执行模式更严格的全新的执行模式

何时:几乎所有新项目的js文件,都要启用严格模式

如何:2种

1.新项目:在每个js文件的开头:”use strict”;  让整个js文件启动严格模式
2.旧项目:逐个函数启动
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: