




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第JavaScriptdefineProperty如何實(shí)現(xiàn)屬性劫持目錄前言描述符
細(xì)說get和set劫持對(duì)象的某個(gè)屬性
劫持對(duì)象的所有屬性
劫持對(duì)象的所有屬性-包括對(duì)象類型的屬性值
defineProperty的缺陷defineProperty還可以掛載屬性
defineProperty還能寫日志
總結(jié)
前言
defineProperty是vue實(shí)現(xiàn)數(shù)據(jù)劫持的核心,本文一點(diǎn)點(diǎn)的說明defineProperty怎么實(shí)現(xiàn)屬性劫持的。
其實(shí)我們一般的操作對(duì)象屬性的方式,增加或者修改屬性,均可以使用Object.defineProperty。
letobj={};
//尋常操作:增加/修改新屬性
obj.a=1;
//等同于:
Object.defineProperty(o,"a",{
value:1,
writable:true,
configurable:true,
enumerable:true
當(dāng)然尋常的例子,我們是不會(huì)這么玩的,太啰嗦了。
但defineProperty可以更精確地添加或修改對(duì)象的屬性。
描述符
先說個(gè)專有名詞:描述符。
其實(shí)就是defineProperty的第三個(gè)參數(shù),是個(gè)對(duì)象。這個(gè)對(duì)象的有以下屬性:
configurable屬性:能不能修改描述符,就是能不能再次修改描述符的其他屬性
enumerable屬性:能不能枚舉該屬性,就是a屬性能不能被for到
writable屬性:能不能修改屬性值,就是能不能這樣修改obj.a=1
value屬性:該屬性的值
get屬性:是個(gè)函數(shù),當(dāng)訪問該屬性的時(shí)候,函數(shù)自動(dòng)調(diào)用,函數(shù)返回值就是該屬性的值
set屬性:是個(gè)函數(shù),當(dāng)修改該屬性的時(shí)候,函數(shù)自動(dòng)調(diào)用,函數(shù)有且只有一個(gè)參數(shù),賦值的新值
注意?。。?/p>
描述符里的value屬性writable屬性與get屬性set屬性是互斥的關(guān)系,只能存在一個(gè)
另外的屬性默認(rèn)值都是false,不想false的話,記得配置哈,不細(xì)說(主要我也不怎么用)。
細(xì)說get和set
get屬性:是個(gè)函數(shù),當(dāng)訪問該屬性的時(shí)候,函數(shù)自動(dòng)調(diào)用,函數(shù)返回值就是該屬性的值
set屬性:是個(gè)函數(shù),當(dāng)修改該屬性的時(shí)候,函數(shù)自動(dòng)調(diào)用,函數(shù)有且只有一個(gè)參數(shù),賦值的新值
默念三遍,背誦。
寫個(gè)get和set的例子輔助理解。
這個(gè)例子必須掌握,弄懂之后基本就掌握了數(shù)據(jù)劫持的精髓了
letobj={};
letvalue=1;
Object.defineProperty(obj,"b",{
get(){
console.log("讀取b屬性",value);
returnvalue;
set(newValue){
console.log("設(shè)置b屬性",newValue);
value=newValue;
//觸發(fā)get函數(shù),get的返回值就是屬性值
console.log(obj.b);
//觸發(fā)set函數(shù),value的值變成了2,注意!??!,此時(shí)內(nèi)存里,屬性值并沒有改變
obj.b=2;
//但是,想要讀取屬性值的時(shí)候,就必然會(huì)觸發(fā)get函數(shù),屬性值也自然就改變了,這個(gè)思想真的很贊
console.log(obj.b);
這里有個(gè)坑:get里是不能有讀取的操作,不然一直死循環(huán),所以使用到getset的地方,總需要借助一個(gè)變量
所以,這里,變量value的值就是屬性的值,如果想要修改屬性,修改value的值即可。
這個(gè)例子弄懂了,get,set的精髓,我覺得也就差不多了。
劫持對(duì)象的某個(gè)屬性
有了剛剛例子的基礎(chǔ),試著寫寫劫持對(duì)象的任意一個(gè)屬性。
functionobserveKey(obj,key){
letvalue=obj[key];
Object.defineProperty(obj,key,{
get(){
console.log("讀取屬性",value);
returnvalue;
set(newValue){
console.log("設(shè)置屬性",newValue);
value=newValue;
letobj={a:1};
observeKey(obj,"a");
//讀取a,觸發(fā)get函數(shù)
console.log(obj.a);
//設(shè)置a,觸發(fā)set函數(shù)
obj.a=1;
劫持對(duì)象的所有屬性
再試試劫持對(duì)象的所有屬性
其實(shí)就是遍歷:
functionobserveObj(obj){
for(letkeyinobj){
//直接使用obj.hasOwnProperty會(huì)提示不規(guī)范
if(Ototype.hasOwnProperty.call(obj,key)){
observeKey(obj,key);
returnobj;
functionobserveKey(obj,key){
letvalue=obj[key];
Object.defineProperty(obj,key,{
get(){
console.log("讀取屬性",value);
returnvalue;
set(newValue){
console.log("設(shè)置屬性",newValue);
value=newValue;
letobj={a:1,b:2};
observeObj(obj);
console.log(obj);
//讀取a,觸發(fā)get函數(shù)
console.log(obj.a);
//設(shè)置a,觸發(fā)set函數(shù)
obj.a=1;
劫持對(duì)象的所有屬性-包括對(duì)象類型的屬性值
上面的有個(gè)缺陷,就是當(dāng)屬性值也是對(duì)象的時(shí)候,不能劫持屬性值,如{a:1,c:{b:1}}
簡(jiǎn)單,遞歸,補(bǔ)上就行。
functionobserveObj(obj){
//加上參數(shù)限制,必須是對(duì)象才有劫持,也是遞歸的終止條件
if(typeofobj!=="object"||obj==null){
return;
for(letkeyinobj){
//直接使用obj.hasOwnProperty會(huì)提示不規(guī)范
if(Ototype.hasOwnProperty.call(obj,key)){
observeKey(obj,key);
//這里劫持該屬性的屬性值,如果不是對(duì)象直接返回,不影響
observeObj(obj[key]);
returnobj;
functionobserveKey(obj,key){
letvalue=obj[key];
Object.defineProperty(obj,key,{
get(){
console.log("讀取屬性",value);
returnvalue;
set(newValue){
console.log("設(shè)置屬性",newValue);
value=newValue;
letobj={a:1,b:2,c:{name:"c"}};
observeObj(obj);
console.log(obj);
//讀取a,觸發(fā)get函數(shù)
console.log(obj.a);
//設(shè)置a,觸發(fā)set函數(shù)
obj.a=1;
//觸發(fā)set函數(shù)
="d";
注意,observeObj這個(gè)函數(shù),不能劫持對(duì)象的新增屬性,只能劫持對(duì)象已有的屬性。
defineProperty的缺陷
不能監(jiān)測(cè)對(duì)象增加屬性
不能監(jiān)測(cè)對(duì)象刪除屬性
不能劫持?jǐn)?shù)組的修改
當(dāng)然數(shù)組的修改可以通過別的方式監(jiān)測(cè)到的,其是通過劫持改變數(shù)組方法實(shí)現(xiàn)的。
以上缺陷,也是vue里面為啥有$set/$delete以及對(duì)數(shù)組只能使用特定方法才能檢測(cè)到。
letobj={a:1,b:[1,2]};
observeObj(obj);
//新增屬性
obj.c=3;
//不會(huì)觸發(fā)get函數(shù)
console.log(obj.c);
//不會(huì)觸發(fā)set函數(shù)
obj.b.push(3);
defineProperty還可以掛載屬性
其實(shí)就是訪問可以簡(jiǎn)寫成,專業(yè)話術(shù),將data上的屬性掛載到options上
相當(dāng)于,用defineProperty,在options上增加新屬性:
//先掛載單個(gè)屬性
//options.data相當(dāng)于sourceoptions相當(dāng)于target
functionproxyKey(target,source,key){
Object.defineProperty(target,key,{
//這里的source[key]相當(dāng)于變量value,所以說最簡(jiǎn)單的那個(gè)例子是核心
get(){
returnsource[key];
set(newValue){
if(newValue===source[key]){
return;
source[key]=newValue;
//遍歷屬性,掛載下
functionproxyObj(target,source){
for(letkeyinsource){
//直接使用obj.hasOwnProperty會(huì)提示不規(guī)范
if(Ototype.hasOwnProperty.call(source,key)){
proxyKey(target,source,key);
letoptions={
data:{name:1}
proxyObj(options,options.data);
console.log();
話說,vue的屬性劫持和掛載屬性,核心原理差不多就是上面這些。
defineProperty還能寫日志
比如obj有個(gè)屬性,此屬性值經(jīng)常變化,想要記錄其所有變化的值,以此可以形成日志。
letobj={a:1};
letlog=[obj.a];
letvalue=obj.a;
Object.defineProperty(obj,"a",{
get(){
returnvalue;
set(newValue){
if(newValue===value){
return;
value=newValue;
log.push(newValue);
obj.a=2;
obj.a=3;
obj.a=4;
//[1,2,3,4]
console.log(log);
通用的可以抽離出一個(gè)類,專門記錄某個(gè)值的變化
classArchiver{
constructor(){
letvalue=null;
this.archive=[];
Object.defineProperty(this,"a",{
get(){
retu
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 倉儲(chǔ)物流配送合同規(guī)范
- 紡織技術(shù)創(chuàng)新思路試題及答案
- 紡織行業(yè)新興市場(chǎng)的開發(fā)與設(shè)計(jì)趨勢(shì)探討試題及答案
- 2025黑龍江大興安嶺林業(yè)集團(tuán)公司招聘撲火隊(duì)設(shè)備操作員73人筆試參考題庫附帶答案詳解
- 2025福建泉州市仙公山風(fēng)景名勝區(qū)有限公司招聘7人筆試參考題庫附帶答案詳解
- 2025年駐馬店全域礦業(yè)開發(fā)有限公司招聘27人筆試參考題庫附帶答案詳解
- 2025年山東省科創(chuàng)集團(tuán)有限公司權(quán)屬企業(yè)招聘12人筆試參考題庫附帶答案詳解
- 哈爾濱委托協(xié)議翻譯電話
- 藝術(shù)類期末試題及答案
- 分布式光伏發(fā)電項(xiàng)目可行性分析與發(fā)展前景
- 中建全套雨季施工方案
- 青春期異性之間的交往課件高中上學(xué)期心理健康主題班會(huì)
- 北京工業(yè)大學(xué)《計(jì)量經(jīng)濟(jì)學(xué)》2023-2024學(xué)年第一學(xué)期期末試卷
- 人工智能應(yīng)用開發(fā)合同
- 猩紅熱課件完整版本
- 肌肉骨骼康復(fù)學(xué)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 高三英語一輪復(fù)習(xí)備考實(shí)踐經(jīng)驗(yàn)分享 課件
- 小學(xué)五年級(jí)體育教案全冊(cè)(人教版)
- 農(nóng)業(yè)保險(xiǎn)理賠服務(wù)操作流程手冊(cè)
- 《交換與路由技術(shù)》 課件全套 曹炯清 第1-9部分 學(xué)習(xí)環(huán)境的搭建- 綜合實(shí)訓(xùn)與技能比賽
- 第30屆WMO初測(cè)2年級(jí)B試卷
評(píng)論
0/150
提交評(píng)論