我们知道闭包最大的意义在于:使得函数的局部变量在函数执行完毕后,仍然驻留内存。很多第三方库和一些公共组件利用闭包这一特性,可以屏蔽函数的内部对象不被外部随意修改。
我们看下面实例:
let o = (function(){
let obj = {
name: 'zhangsan',
age : 18
}
return{
get:function(k){
return obj[k];
}
}
})();
console.log(o.get('name'))
console.log(o.get('age'))
//obj对象无法直接访问。
/*
obj.name = 'lisi';
console.log(o.get('name'))
console.log(o.get('age'))
*/
运行结果:
zhangsan
18
但是,这里我们忽略了闭包代码存在的提权漏洞现象。我们可以利用Object.defineProperty获取闭包对象。
程序改写如下:
let o = (function(){
let obj = {
name: 'zhangsan',
age : 18
}
//Object.setPrototypeOf(obj,null);
return{
get:function(k){
return obj[k];
}
}
})();
console.log(o.get('name'))
console.log(o.get('age'))
Object.defineProperty(Object.prototype,'primaryObject',{
get(){
return this;
}
});
console.log(o.get('primaryObject'))
let primaryObj =o.get('primaryObject')
primaryObj.name = 'lisi';
primaryObj.age = 20;
console.log(o.get('name'))
console.log(o.get('age'))
运行结果:
zhangsan
18
{ name: 'zhangsan', age: 18 }
lisi
20
解决这个漏洞有以下两种方案:
1).断开原型链。
let o = (function(){
let obj = {
name: 'zhangsan',
age : 18
}
//断开原型链
Object.setPrototypeOf(obj,null);
return{
get:function(k){
return obj[k];
}
}
})();
console.log(o.get('name'))
console.log(o.get('age'))
Object.defineProperty(Object.prototype,'primaryObject',{
get(){
return this;
}
});
console.log(o.get('primaryObject'))
let primaryObj =o.get('primaryObject')
primaryObj.name = 'lisi';
primaryObj.age = 20;
console.log(o.get('name'))
console.log(o.get('age'))
2).使用hasOwnProperty判断是否是对象的真正属性。
let o = (function(){
let obj = {
name: 'zhangsan',
age : 18
}
//Object.setPrototypeOf(obj,null);
return{
get:function(k){
if(obj.hasOwnProperty(k)) {
return obj[k];
}
}
}
})();
console.log(o.get('name'))
console.log(o.get('age'))
Object.defineProperty(Object.prototype,'primaryObject',{
get(){
return this;
}
});
console.log(o.get('primaryObject'))
let primaryObj =o.get('primaryObject')
primaryObj.name = 'lisi';
primaryObj.age = 20;
console.log(o.get('name'))
console.log(o.get('age'))