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'
上面的代碼是一個閉包的函數(shù)保護了里面的對象不被修改
可以想象成第三方的庫 保護了內(nèi)部的東西不被外面所直接調(diào)用
首先 我們可以通過get訪問到自身的成員就比如
let target1 = obj('text1')
我們可以訪問到target對象上的所有成員
當然我們也可以訪問到該對象原型上的成員 Object.prototype
解答
我們可以通過obj.get('text2')訪問到text2
這里我們還可以訪問到valueOf
let tar = obj.get('valueOf')
返回的是object原型上的那個函數(shù)[Function:valueOf]
對象上的valueOf會返回它自身
于是我們就可以調(diào)用這個函數(shù)
let tar = obj.get('valueOf')()
這里的tar就是上面tartget本身了
但是你如果這樣調(diào)用你會發(fā)現(xiàn)它在報錯
TypeError: Cannot convert undefined or null to object
? ? at valueOf (<anonymous>)
? ? at Object.<anonymous>
這里的原因是this的指向問題了不恭,這里就牽涉到我們應該怎么樣去調(diào)用這個valueOf,但是在這里我們是直接通過這個函數(shù)本身去調(diào)用的,所以這里的this指向就會出現(xiàn)問題,如果向上面那么調(diào)用valueOf這個函數(shù) ,那么this會指向全局,在嚴格模式下就會指向undefind
上面的代碼等價于
const valueOf = Object.prototype.valueOf
obj.get('valueOf')() === valueOf()
在js里面有沒有一種情況就是在讀某一個屬性的時候就直接是一個函數(shù)調(diào)用呢?
比如當這個屬性是一訪問器的時候 他就可以是一個函數(shù)調(diào)用
Object.definProperty(Object.prototype,'text',{
? ? get(){
? ? ? ? return this
? ? }
})
這里我們把text傳入進去
這里我們慢慢來解答
這里傳入的text會讀取問題函數(shù)中的target對象 但是它找不到text
他就會到原型上去找text 然后呢他就會在原型上找到text這個屬性
這里當它在讀取的時候 誰在調(diào)用它 this就指向誰 于是這個this就是這個函數(shù)本身
于是我們就得到了上面的target對象的整個信息了
所以我們就可以得到一下答案了
let obj = obj.get('text');
obj.text1 = 123123;
obj.text2 = 123401;
obj.text3 = '新增的';
這里我們就達到了修改閉包函數(shù)對象里的目的了
這里多嘴一句 假如這是我們寫好的第三方庫
如果有人要串改的話就會有風險
我們要怎么防范這種情況出現(xiàn)呢
第一種情況就是看訪問的屬性是不是target本身的屬性
不能使它原型上的屬性一定要是它本身的屬性
第二種情況就是通過設(shè)置target對象原型為空 這樣也可以達到目的
因為這里主要就是靠原型去修改的那個對象 如果它沒有原型 它也就沒有了漏洞可鉆了