一、如何在不改变下面代码的情况下,修改obj
对象
js
var o = (function () {
var obj = {
a: 1,
b: 2,
};
return {
get: function (k) {
return obj[k];
}
}
})();
题解:
- 以上程序的目的,主要是屏蔽
obj
,不可让外面直接访问它,只能读取它的某个属性,这样保护了这个对象的完整。相当于一个第三方库, 提供的获取的api
,屏蔽了它内部的一些东西,不被外界直接访问。 - 以上的代码,能不能就使用它提供的
api
达到破坏它的目的呢? 其实是可以做到的。 - 以上的代码,提供的
api
实际上有点权限过大了,可以通过api
访问到这obj
的任何成员,除了他自身的成员之外,还可以访问原型上的成员,obj
的原型不就是Object.prototype
,同时根据对象上的valueOf
返回自身的特性,obj.valueOf
返回的就是obj
这个对象本身,那是不是可以使用o.get('valueOf')()
调用这个函数,会发现报错Cannot convert undefined or null to object
,这就涉及到this
的指向问题了,o.get('valueOf')()
调用,this
的 指向全局,也就是在严格模式下会指向undefined
。根源在于get
函数里面直接返回的是某个成员,如果这边直接是函数调用的话,return obj[k]()
,那就没问题了。 - 在
js
里有没有一种可能,当读取某个对象属性的时候,就直接是一个函数调用。有可能,当这个属性是一个访问器的时候。jsObject.defineProperty(Object.prototype, 'abc', { get() { return this; } })
- 通过这个漏洞,我们就可以拿到这个对象js
var obj2 = o.get('abc'); obj2.c = 2; console.log(o.get('c'))
- 保护措施
- 方案一:获取的时候判断是否是对象本身的属性js
var o = (function () { var obj = { a: 1, b: 2, }; return { get: function (k) { if (obj.hasOwnProperty(k)) { return obj[k]; } return undefined; } } })();
- 方案二:没有使用到原型,直接将原型设置为空js
var o = (function () { var obj = { a: 1, b: 2, }; Object.setPrototypeOf(obj, null); return { get: function (k) { return obj[k]; } } })();
- 方案一:获取的时候判断是否是对象本身的属性