var obj = (function (){
var target = {
text1:"目标1",
text2:"目标2"
};
return {
get:function(key){
return target[key]
}
}
})()
题目:怎么才能在不改变下面代码的情况下修改tartget对象
举例:
let target1 = obj('text1')
// target1 = '目标1'
let target1 = obj('text2')
// target1 = '目标2'
上面的代码是一个闭包的函数保护了里面的对象不被修改
可以想象成第三方的库 保护了内部的东西不被外面所直接调用
首先 我们可以通过get访问到自身的成员就比如
let target1 = obj('text1')
我们可以访问到target对象上的所有成员
当然我们也可以访问到该对象原型上的成员 Object.prototype
解答
我们可以通过obj.get('text2')访问到text2
这里我们还可以访问到valueOf
let tar = obj.get('valueOf')
返回的是object原型上的那个函数[Function:valueOf]
对象上的valueOf会返回它自身
于是我们就可以调用这个函数
let tar = obj.get('valueOf')()
这里的tar就是上面tartget本身了
但是你如果这样调用你会发现它在报错
TypeError: Cannot convert undefined or null to object
at valueOf (<anonymous>)
at Object.<anonymous>
这里的原因是this的指向问题了,这里就牵涉到我们应该怎么样去调用这个valueOf,但是在这里我们是直接通过这个函数本身去调用的,所以这里的this指向就会出现问题,如果向上面那么调用valueOf这个函数 ,那么this会指向全局,在严格模式下就会指向undefind
上面的代码等价于
const valueOf = Object.prototype.valueOf
obj.get('valueOf')() === valueOf()
在js里面有没有一种情况就是在读某一个属性的时候就直接是一个函数调用呢?
比如当这个属性是一访问器的时候 他就可以是一个函数调用
Object.definProperty(Object.prototype,'text',{
get(){
return this
}
})
这里我们把text传入进去
这里我们慢慢来解答
这里传入的text会读取问题函数中的target对象 但是它找不到text
他就会到原型上去找text 然后呢他就会在原型上找到text这个属性
这里当它在读取的时候 谁在调用它 this就指向谁 于是这个this就是这个函数本身
于是我们就得到了上面的target对象的整个信息了
所以我们就可以得到一下答案了
let obj = obj.get('text');
obj.text1 = 123123;
obj.text2 = 123401;
obj.text3 = '新增的';
这里我们就达到了修改闭包函数对象里的目的了
这里多嘴一句 假如这是我们写好的第三方库
如果有人要串改的话就会有风险
我们要怎么防范这种情况出现呢
第一种情况就是看访问的属性是不是target本身的属性
不能使它原型上的属性一定要是它本身的属性
第二种情况就是通过设置target对象原型为空 这样也可以达到目的
因为这里主要就是靠原型去修改的那个对象 如果它没有原型 它也就没有了漏洞可钻了