用proxy寫乙個遞迴來監聽巢狀物件甚至JSON

2021-08-16 07:24:35 字數 3701 閱讀 7699

之前的這篇文章

[其實那個監聽方式有個大bug,當不停的update 監聽物件以後就會導致記憶體洩漏。因為每次在呼叫get的時候都會生成乙個新的proxy,後來才知道是多傻。

經過我一天時間的思考,用了乙個遞迴的方法去解決巢狀物件的監聽問題。

下面是**:

//傳遞兩個引數,乙個是object, 乙個是proxy的handler

//如果是不是巢狀的object,直接加上proxy返回,如果是巢狀的object,那麼進入addsubproxy進行遞迴。

function todeepproxy(object, handler)

}object = new proxy(object, handler)

}//是不是乙個pure object,意思就是object裡面沒有再巢狀object了

function ispureobject(object) else }}

return

true;}}

這個函式的關鍵點就在於,你是從巢狀物件的第乙個屬性進行判斷加proxy還是從巢狀物件的最末端先進行判斷加proxy, 此函式是後者。

前者我也除錯過,行不通,就不贅述了。而且前者向後遞迴有個問題,在初始化的時候會觸發不必要的get/set 指令。

乙個有趣的事情是,在js中array也是object, 所以這個方法也是可以監聽array的, 衍生開去,這個方法可以監聽整個json資料結構。

但是這個函式有個缺點,就是會直接汙染 需要監聽的target, 如果你不想target被汙染,那麼這個方法就不可行了。

下面是用法:

//這是乙個巢狀了物件和陣列的物件

letobject = }},

class: 5,

arr: [1, 2, ],

age:

}//這是乙個巢狀了物件和陣列的陣列

let objectarr = [, arr1:[1,2]}, 2, 3, 4, 5, 6]

//這是proxy的handler

let handler = ,

set(target, property, value)

}//變成監聽物件

object = todeepproxy(object, handler);

objectarr = todeepproxy(objectarr, handler);

//進行一系列操作

console.time('pro')

objectarr.length

objectarr[3];

objectarr[2]=10

objectarr[0].name.first = 'ss'

objectarr[0].arr1[0]

object.name.first.second.third = 'yyyyy'

object.class = 6;

object.name.first.four

object.arr[2].arr1

object.age.age1 = 20;

console.timeend('pro')

下面是結果:

可以看到,每次操作,不管物件,巢狀物件,陣列,巢狀陣列都有被呼叫到,而且在3ms左右完成,沒有記憶體洩漏的問題。

接下來封裝一下,用兩種方法封裝,一種是類,一種是函式

類:

class watch ;

this.eventupdated = new customevent('updated', customeventdata);

this.eventread = new customevent('read', customeventdata);

this.eventchanged = new customevent('changed', customeventdata);

this.targetobj = obj;

}createproxy() ,

set(target, property, value)

}return todeepproxy(_this.targetobj, handler);

function todeepproxy(object, handler)

}object = new proxy(object, handler)

}function ispureobject(object) else }}

return

true;}}

}on(eventstr, callback) );

} else );}}

}}

用法:

let obj1 = 

let obj2 =

let watcher = new watch(obj1);

let watcher2 = new watch(obj2);

obj1 = watcher.createproxy();

obj2 = watcher2.createproxy();

watcher.on('read, updated', function

() );

watcher2.on('read, updated', function

() );

obj1.name

obj2.class

這是用了addeventlistener來監聽物件的變化,但是問題是要呼叫全域性變數document

下面用函式的方法:

function watchout(obj, opts) ,

set(target, property, value)

}return todeepproxy(obj, handler);

function todeepproxy(object, handler)

}object = new proxy(object, handler)

}function ispureobject(object) else }}

return

true;}}

}

呼叫方法:},,

read(target, property) ,

beforeupdated(target, property, value) ,

beforechanged(target, property, value) ,

updated(target, property, value) ,

changed(target, property, value)

});obj3.name.second

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

經過我的測試發現,如果用上面的方法對乙個巢狀對像進行todeepproxy以後,如果對此proxy進行賦值,而且這個值是個物件時,那麼還是不能對賦的新值進行監聽,因為我們沒有在handler的set裡面對新值進行**。

所以我們改下handler。

let handler = ,

set(target, property, value)

return result;}}

用golang寫乙個proxy

我複雜的網路環境中,proxy是個很有用的工具,我們可以通過proxy 幫我們完成網路流量的 這個proxy得先能接收請求,所以這裡先啟動乙個tcp的監聽,獲取請求 func s server start glog.infof proxy listen in s,waiting for connec...

用python寫乙個restful API

coding utf 8 package.module python實現的圖書的乙個restful api.restful api 一般模式 get select 從伺服器取出資源 一項或多項 post create 在伺服器新建乙個資源。put update 在伺服器更新資源 客戶端提供改變後的完...

用python寫乙個蛇形矩陣

蛇形矩陣,如 10 11 12 1 9 16 13 2 8 15 14 3 7 6 5 4從右上角大回環,其實挺簡單,思路想明白了就順了。這樣的矩陣可以看做二維陣列,python對陣列的寫法很麻煩,用numpy生成就簡單多了 myarray np.zeros n,n dtype np.int16 有...