亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript中的數據劫持和數據代理使用

 更新時間:2025年02月21日 17:13:09   作者:遇見很ok  
文章主要介紹了數據劫持(Object.defineProperty)和數據代理(Proxy)兩種方式在JavaScript中的應用,并通過生活中的例子來詳細解釋它們的工作原理和使用場景,文章還對比了兩種方式的優(yōu)缺點,并指出了它們在Vue.js中的應用

一、數據劫持(Data Hijacking)

1. 生活中的例子

假設你開了一家餐廳,你雇了一個 “賬房先生”(收銀員),他的工作是:

  • 任何客人 查詢賬單 時,他都會記錄查詢行為,并告訴客人正確的金額。
  • 任何客人 修改賬單 時,他都會檢查金額是否合理,并記錄修改情況。

現(xiàn)實中的“賬房先生”就是 Object.defineProperty(),它攔截每個數據的讀取和修改。

2. 代碼示例

我們用 Object.defineProperty() 來模擬這個 “賬房先生”:

let bill = {};  // 創(chuàng)建賬單對象

Object.defineProperty(bill, 'amount', {
  get() {
    console.log('客人查詢了賬單金額');
    return 100; // 假設賬單金額是100
  },
  set(value) {
    console.log(`客人修改了賬單金額為 ${value}`);
  }
});

console.log(bill.amount);  // 觸發(fā) get 方法,查詢金額
bill.amount = 200;         // 觸發(fā) set 方法,修改金額

運行結果:

客人查詢了賬單金額
100
客人修改了賬單金額為 200

問題:

  • 這個方法 只能劫持已sh()、pop() 這樣的操作不會觸發(fā) set。
  • 必須對每個屬性單獨定義 get/set,如
  • 有的屬性,如果 bill 里沒有 amount,defineProperty 無法監(jiān)聽到新增的 amount 屬性。
  • 無法監(jiān)聽數組變化,比如 pu
  • 果對象有很多屬性,就要定義很多次,性能較低。

二、數據代理(Data Proxy)

1. 生活中的例子

假設你家有一個 智能管家(類似于小愛同學、Siri),你可以問他:

  • "今天天氣怎么樣?" 他會去查天氣然后告訴你(相當于攔截 讀取 操作)。
  • "幫我把燈光調亮一些" 他會控制家里的燈光調亮(相當于攔截 修改 操作)。

智能管家就是 Proxy,它可以代理整個房子里所有的設備,而不需要逐個綁定(不像 Object.defineProperty() 必須單獨劫持每個設備的控制)。

2. 代碼示例

Proxy 實現(xiàn)智能管家的功能:

let house = { temperature: 22, light: 'off' }; // 房子里的設備

let smartHouse = new Proxy(house, {
  get(target, key) {
    console.log(`查詢 ${key} 的狀態(tài):${target[key]}`);
    return target[key];
  },
  set(target, key, value) {
    console.log(`修改 ${key} 的狀態(tài)為 ${value}`);
    target[key] = value;
    return true;
  }
});

console.log(smartHouse.temperature);  // 觸發(fā) get,查詢溫度
smartHouse.light = 'on';              // 觸發(fā) set,修改燈光狀態(tài)

運行結果:

查詢 temperature 的狀態(tài):22
修改 light 的狀態(tài)為 on

Proxy 的優(yōu)勢:

  • 可以代理整個對象,不用為每個屬性單獨定義 get/set
  • 支持監(jiān)聽新增屬性,比如 house.newDevice = 'TV' 也能被攔截!
  • 支持數組,例如監(jiān)聽 push()、pop() 這些操作。

三、對比總結

對比項數據劫持(Object.defineProperty)數據代理(Proxy)
Vue 版本Vue 2.xVue 3.x
監(jiān)聽對象只能監(jiān)聽已有的屬性可以監(jiān)聽整個對象
監(jiān)聽新增/刪除屬性不能監(jiān)聽(需 Vue.set)可直接監(jiān)聽
監(jiān)聽數組需要重寫數組方法原生支持
深層嵌套需要遞歸遍歷訪問時自動代理
兼容性ES5 及以上僅支持 ES6 及以上

四、再舉一個更貼近開發(fā)的例子

使用 Object.defineProperty() 監(jiān)聽對象

let person = { name: 'Alice', age: 25 };

function makeReactive(obj) {
  for (let key in obj) {
    let value = obj[key];
    Object.defineProperty(obj, key, {
      get() {
        console.log(`讀取 ${key}: ${value}`);
        return value;
      },
      set(newVal) {
        console.log(`修改 ${key} 為 ${newVal}`);
        value = newVal;
      }
    });
  }
}

makeReactive(person);

console.log(person.name);  // 讀取 name
person.age = 30;           // 修改 age

問題:

  • 不能監(jiān)聽 person.newProp = 'test' 這樣的新增屬性。
  • 不能監(jiān)聽 delete person.age 這樣的刪除操作。

使用 Proxy 監(jiān)聽整個對象

let person = { name: 'Alice', age: 25 };

let reactivePerson = new Proxy(person, {
  get(target, key) {
    console.log(`讀取 ${key}: ${target[key]}`);
    return target[key];
  },
  set(target, key, value) {
    console.log(`修改 ${key} 為 ${value}`);
    target[key] = value;
    return true;
  },
  deleteProperty(target, key) {
    console.log(`刪除屬性 ${key}`);
    return delete target[key];
  }
});

console.log(reactivePerson.name);  // 讀取 name
reactivePerson.age = 30;           // 修改 age
reactivePerson.newProp = 'test';   // 監(jiān)聽新增屬性
delete reactivePerson.age;         // 監(jiān)聽刪除屬性

優(yōu)勢:

  • Proxy 可以監(jiān)聽對象的新增/刪除屬性,而 Object.defineProperty() 不行!
  • Proxy 可以監(jiān)聽數組的變化,而 Object.defineProperty() 不能監(jiān)聽 push()splice()
  • Proxy 可以代理整個對象,而 Object.defineProperty() 需要遍歷所有屬性,性能較差。

五、總結

概念方式適用場景優(yōu)勢
數據劫持Object.defineProperty()Vue 2.x兼容性好,支持老瀏覽器,但不能監(jiān)聽新增/刪除屬性
數據代理ProxyVue 3.x功能更強,可監(jiān)聽新增/刪除,支持數組操作

結論:

  • 如果是 Vue 2,只能用 Object.defineProperty() 來實現(xiàn)數據劫持。
  • 如果是 Vue 3,推薦用 Proxy,因為它更強大,能處理所有數據變化。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

最新評論