最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript Proxy與Reflect的實現(xiàn)

 更新時間:2026年02月13日 10:56:17   作者:wuhen_n  
本文主要介紹了JavaScript Proxy與Reflect的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

在 JavaScript 中如何攔截對象的讀取、修改、刪除操作?Vue3的響應(yīng)式系統(tǒng)如何實現(xiàn)?本文將深入講解 JavaScript 的元編程世界,探索 Proxy 和 Reflect 的奧秘。

前言:從Vue3的響應(yīng)式說起

// Vue3的響應(yīng)式數(shù)據(jù)實現(xiàn)原理
const reactive = (target) => {
    return new Proxy(target, {
        get(target, key, receiver) {
            track(target, key); // 依賴收集
            return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {
            const result = Reflect.set(target, key, value, receiver);
            trigger(target, key); // 觸發(fā)更新
            return result;
        }
    });
};

Vue3的響應(yīng)式數(shù)據(jù)實現(xiàn)原理的背后,就是 Proxy 和 Reflect 。理解它們,我們就能真正掌握 JavaScript 元編程的能力。

理解Proxy與Reflect

什么是Proxy(代理)?

Proxy 對象用于創(chuàng)建一個對象的代理,從而實現(xiàn)對基本操作的攔截和自定義(如屬性查找、賦值、枚舉、函數(shù)調(diào)用等)。

Proxy工作流程示意圖

┌─────────┐   操作請求   ┌─────────┐   轉(zhuǎn)發(fā)操作    ┌─────────┐
│ 客戶端   │───────────→ │  Proxy  │───────────→ │ 目標(biāo)對象 │
│         │             │  代理    │             │         │
│         │←─────────── │         │←─────────── │         │
└─────────┘   響應(yīng)結(jié)果   └─────────┘   實際結(jié)果    └─────────┘
                ↓                           ↓
         ┌─────────────┐            ┌─────────────┐
         │ 攔截和自定義  │            │ 原始行為     │
         │   (陷阱)   │            │             │
         └─────────────┘            └─────────────┘

什么是Reflect(反射)?

Reflect 是一個內(nèi)置的對象,它提供攔截 JavaScript 操作的方法。這些方法與 Proxy 的陷阱方法一一對應(yīng)。

為什么需要Reflect?

  1. 統(tǒng)一的操作API
  2. 更好的錯誤處理(返回布爾值而非拋出異常)
  3. 與Proxy陷阱方法一一對應(yīng)

代理基礎(chǔ):創(chuàng)建第一個代理

// 目標(biāo)對象
const target = {
  name: '張三',
  age: 30
};

// 處理器對象(包含陷阱方法)
const handler = {
  // 攔截屬性讀取
  get(target, property, receiver) {

    // 添加自定義邏輯
    if (property === 'age') {
      return `${target[property]}歲`;
    }

    // 默認行為:使用Reflect
    return Reflect.get(target, property, receiver);
  },

  // 攔截屬性設(shè)置
  set(target, property, value, receiver) {
    // 添加驗證邏輯
    if (property === 'age' && (value < 0 || value > 150)) {
      console.warn('年齡必須在0-150之間');
      return false; // 返回false表示設(shè)置失敗
    }

    // 默認行為:使用Reflect
    return Reflect.set(target, property, value, receiver);
  }
};

// 創(chuàng)建代理
const proxy = new Proxy(target, handler);

console.log(proxy.name);  // 張三
console.log(proxy.age);   // 30歲
console.log(target.age); // 30

13種可攔截的陷阱方法

完整陷阱方法概覽

const completeHandler = {
  // 1. 屬性訪問攔截
  get(target, prop, receiver) {
    console.log(`get: ${prop}`);
    return Reflect.get(target, prop, receiver);
  },

  // 2. 屬性賦值攔截
  set(target, prop, value, receiver) {
    console.log(`set: ${prop} = ${value}`);
    return Reflect.set(target, prop, value, receiver);
  },

  // 3. in操作符攔截
  has(target, prop) {
    console.log(`has: ${prop}`);
    return Reflect.has(target, prop);
  },

  // 4. delete操作符攔截
  deleteProperty(target, prop) {
    console.log(`delete: ${prop}`);
    return Reflect.deleteProperty(target, prop);
  },

  // 5. 構(gòu)造函數(shù)調(diào)用攔截
  construct(target, args, newTarget) {
    console.log(`construct with args:`, args);
    return Reflect.construct(target, args, newTarget);
  },

  // 6. 函數(shù)調(diào)用攔截
  apply(target, thisArg, args) {
    console.log(`apply: thisArg=`, thisArg, 'args=', args);
    return Reflect.apply(target, thisArg, args);
  },

  // 7. Object.getOwnPropertyDescriptor攔截
  getOwnPropertyDescriptor(target, prop) {
    console.log(`getOwnPropertyDescriptor: ${prop}`);
    return Reflect.getOwnPropertyDescriptor(target, prop);
  },

  // 8. Object.defineProperty攔截
  defineProperty(target, prop, descriptor) {
    console.log(`defineProperty: ${prop}`, descriptor);
    return Reflect.defineProperty(target, prop, descriptor);
  },

  // 9. 原型訪問攔截
  getPrototypeOf(target) {
    console.log('getPrototypeOf');
    return Reflect.getPrototypeOf(target);
  },

  // 10. 原型設(shè)置攔截
  setPrototypeOf(target, prototype) {
    console.log(`setPrototypeOf:`, prototype);
    return Reflect.setPrototypeOf(target, prototype);
  },

  // 11. 可擴展性判斷攔截
  isExtensible(target) {
    console.log('isExtensible');
    return Reflect.isExtensible(target);
  },

  // 12. 防止擴展攔截
  preventExtensions(target) {
    console.log('preventExtensions');
    return Reflect.preventExtensions(target);
  },

  // 13. 自身屬性枚舉攔截
  ownKeys(target) {
    console.log('ownKeys');
    return Reflect.ownKeys(target);
  }
};

陷阱方法詳細解析

1. get陷阱:屬性訪問攔截

get() 會在獲取屬性值的操作中被調(diào)用:

const getHandler = {
  get(target, property, receiver) {
    // 處理不存在的屬性
    if (!(property in target)) {
      throw new Error(`屬性不存在: ${property}`);
    }

    // 處理私有屬性(約定以_開頭的屬性為私有)
    if (property.startsWith('_')) {
      throw new Error(`不能訪問私有屬性: ${property}`);
    }
    return Reflect.get(target, property, receiver);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)對象
    2. property:引用的目標(biāo)對象上的屬性
    3. receiver:代理對象
  • 返回值說明:返回值無限制

2. set陷阱:屬性賦值攔截

set() 會在設(shè)置屬性值的操作中被調(diào)用:

const setHandler = {
  set(target, property, value, receiver) {
    // 只讀屬性檢查(約定以$開頭的屬性為只讀)
    if (property.startsWith('$')) {
      throw new Error(`屬性不可修改: ${property}`);
    }
    // 執(zhí)行設(shè)置
    return Reflect.set(target, property, value, receiver);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)對象
    2. property:引用的目標(biāo)對象上的屬性
    3. value:要給屬性設(shè)置的值
    4. receiver:代理對象
  • 返回值說明:返回 true 表示成功;返回false表示失敗。

3. has陷阱:in操作符攔截

has() 會在 in 操作符中被調(diào)用:

const hasHandler = {
  has(target, property) {
    // 隱藏某些屬性(不在in操作中暴露)
    const hiddenProperties = ['password', 'token', '_internal'];
    if (hiddenProperties.includes(property)) {
      console.log(`隱藏屬性: ${property}`);
      return false;
    }

    // 虛擬屬性(不存在但返回true)
    const virtualProperties = ['isAdmin', 'hasAccess'];
    if (virtualProperties.includes(property)) {
      console.log(`虛擬屬性: ${property}`);
      return true;
    }

    return Reflect.has(target, property);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)對象
    2. value:要給屬性設(shè)置的值
  • 返回值說明:返回布爾值表示屬性是否存在,返回非布爾型會被轉(zhuǎn)成布爾型。

注:Object.keys() 不受 has() 影響,仍會返回所有屬性。

4. apply陷阱:函數(shù)調(diào)用攔截

apply() 會在調(diào)用函數(shù)時被調(diào)用:

const applyHandler = {
  apply(target, thisArg, argumentsList) {
    // 參數(shù)驗證
    if (target.name === 'calculate') {
      if (argumentsList.length < 2) {
        throw new Error('calculate函數(shù)需要至少2個參數(shù)');
      }
      if (!argumentsList.every(arg => typeof arg === 'number')) {
        throw new Error('calculate函數(shù)的所有參數(shù)必須是數(shù)字');
      }
    }
    return Reflect.apply(target, thisArg, argumentsList);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)對象
    2. thisArg:調(diào)用函數(shù)時的this參數(shù)
    3. argumentsList:調(diào)用函數(shù)時的參數(shù)列表
  • 返回值說明:返回值無限制

5. construct陷阱:構(gòu)造函數(shù)攔截

construct() 會在調(diào)用函數(shù)時被調(diào)用:

const constructHandler = {
  construct(target, argumentsList, newTarget) {
    // 單例模式:確保只有一個實例
    if (target._instance) {
      console.log('返回現(xiàn)有實例');
      return target._instance;
    }

    // 創(chuàng)建實例
    const instance = Reflect.construct(target, argumentsList, newTarget);

    // 為單例保存實例
    if (target.name === 'Singleton') {
      target._instance = instance;
    }

    // 為實例添加額外屬性
    instance.createdAt = new Date();
    instance._id = Math.random().toString(36).substr(2, 9);

    console.log('創(chuàng)建新實例,ID:', instance._id);
    return instance;
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
    2. argumentsList:傳給目標(biāo)構(gòu)造函數(shù)的參數(shù)列表
    3. newTarget:最初被調(diào)用的構(gòu)造函數(shù)
  • 返回值說明:必須返回一個對象

6. ownKeys陷阱:影響Object.keys()等遍歷

ownKeys() 會在Object.keys()及類似方法中被調(diào)用:

const ownKeysHandler = {
  ownKeys(target) {
    // 過濾掉以_開頭的私有屬性
    const keys = Reflect.ownKeys(target);
    return keys.filter(key => {
      if (typeof key === 'string') {
        return !key.startsWith('_');
      }
      return true;
    });
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
  • 返回值說明:必須返回一個包含字符串或符號的可枚舉對象

7. getOwnPropertyDescriptor陷阱:影響Object.getOwnPropertyDescriptor()

getOwnPropertyDescriptor() 會在Object.getOwnPropertyDescriptor()方法中被調(diào)用:

const getOwnPropertyDescriptorHandler = {
  getOwnPropertyDescriptor(target, prop) {
    // 隱藏私有屬性的描述符
    if (prop.startsWith('_')) {
      return undefined;
    }
    return Reflect.getOwnPropertyDescriptor(target, prop);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
    2. prop:引用的目標(biāo)對象上的字符串屬性
  • 返回值說明:必須返回對象,或在屬性不存在時返回 undefined

8. defineProperty陷阱:攔截Object.defineProperty()

defineProperty() 會在Object.defineProperty()方法中被調(diào)用:

const definePropertyHandler = {
  defineProperty(target, prop, descriptor) {
    // 防止修改只讀屬性
    if (prop === 'id' && target.id) {
      console.warn('id屬性是只讀的');
      return false;
    }
    return Reflect.defineProperty(target, prop, descriptor);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
    2. prop:引用的目標(biāo)對象上的字符串屬性
    3. descriptor:包含可選的enumrable、configurable、value、get 和 set 等定義的對象
  • 返回值說明:必須返回布爾值,表示屬性是否成功定義

9. deleteProperty陷阱:攔截delete操作

deleteProperty() 會在 delete 操作中被調(diào)用:

const deletePropertyHandler = {
  deleteProperty(target, prop) {
    // 防止刪除重要屬性
    const protectedProps = ['id', 'createdAt'];
    if (protectedProps.includes(prop)) {
      console.warn(`不能刪除受保護的屬性: ${prop}`);
      return false;
    }
    return Reflect.deleteProperty(target, prop);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
    2. property:引用的目標(biāo)對象上的屬性
  • 返回值說明:必須返回布爾值,表示屬性是否被成功刪除

10. preventExtensions陷阱:攔截Object.preventExtensions()

preventExtensions() 會在 Object.preventExtensions() 方法中被調(diào)用:

const preventExtensionsHandler = {
  preventExtensions(target) {
    // 在阻止擴展前添加標(biāo)記
    target._frozenAt = new Date();
    return Reflect.preventExtensions(target);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
  • 返回值說明:必須返回布爾值,表示 target 是否已經(jīng)不可擴展

11. getPrototypeOf陷阱:攔截Object.getPrototypeOf()

getPrototypeOf() 會在 Object.getPrototypeOf() 方法中被調(diào)用:

const getPrototypeOfHandler = {
  getPrototypeOf(target) {
    return Reflect.getPrototypeOf(target);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
  • 返回值說明:必須返回對象或null

12. setPrototypeOf陷阱:攔截Object.setPrototypeOf()

setPrototypeOf() 會在 Object.setPrototypeOf() 方法中被調(diào)用:

const setPrototypeOfHandler = {
  setPrototypeOf(target, prototype) {
    return Reflect.setPrototypeOf(target, prototype);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
    2. property:引用的目標(biāo)對象上的屬性
  • 返回值說明:必須返回布爾值,表示原型賦值是否成功

13. isExtensible陷阱:攔截Object.isExtensible()

isExtensible() 會在 Object.isExtensible() 方法中被調(diào)用:

const isExtensibleHandler = {
  isExtensible(targete) {
    return Reflect.isExtensible(targete);
  }
};
  • 參數(shù)說明:
    1. target:目標(biāo)構(gòu)造函數(shù)
  • 返回值說明:必須返回布爾值,表示 target 是否可擴展

可撤銷代理

什么是可撤銷代理?

可撤銷代理(Revocable Proxy)是一種特殊的代理,它提供了一個 revoke() 方法,調(diào)用該方法后,代理將不再可用,所有對代理的操作都會拋出 TypeError,即:會中斷代理對象和目標(biāo)對象之間的聯(lián)系。

const target = { name: 'zhangsan' };
const handler = {
  get() {
    return 'foo';
  }
}
// 創(chuàng)建可撤銷代理
const { proxy, revoke } = Proxy.revocable(target, handler);

console.log(proxy.name); // 'zhangsan'

// 撤銷代理
revoke();

// 代理已失效
try {
  console.log(proxy.name); // TypeError: Cannot perform 'get' on a proxy that has been revoked
} catch (error) {
  console.log('錯誤:', error.message);
}

實現(xiàn)響應(yīng)式數(shù)據(jù)(Vue3原理)

// 簡易版Vue3響應(yīng)式系統(tǒng)
class ReactiveSystem {
  constructor() {
    this.targetMap = new WeakMap(); // 存儲依賴關(guān)系
    this.effectStack = [];          // 當(dāng)前正在執(zhí)行的effect
    this.batchQueue = new Set();    // 批量更新隊列
    this.isBatching = false;        // 是否處于批量更新模式
  }

  // 核心:創(chuàng)建響應(yīng)式對象
  reactive(target) {
    return new Proxy(target, {
      get(target, key, receiver) {
        // 獲取原始值
        const result = Reflect.get(target, key, receiver);

        // 依賴收集
        track(target, key);

        // 深度響應(yīng)式(如果值是對象,繼續(xù)代理)
        if (result && typeof result === 'object') {
          return reactive(result);
        }

        return result;
      },

      set(target, key, value, receiver) {
        // 獲取舊值
        const oldValue = target[key];

        // 設(shè)置新值
        const result = Reflect.set(target, key, value, receiver);

        // 觸發(fā)更新(值確實改變時才觸發(fā))
        if (oldValue !== value) {
          trigger(target, key);
        }

        return result;
      },

      // 處理刪除操作
      deleteProperty(target, key) {
        const hasKey = key in target;
        const result = Reflect.deleteProperty(target, key);

        if (hasKey && result) {
          trigger(target, key);
        }

        return result;
      }
    });
  }

  // 依賴收集
  track(target, key) {
    if (this.effectStack.length === 0) return;

    let depsMap = this.targetMap.get(target);
    if (!depsMap) {
      depsMap = new Map();
      this.targetMap.set(target, depsMap);
    }

    let dep = depsMap.get(key);
    if (!dep) {
      dep = new Set();
      depsMap.set(key, dep);
    }

    // 收集當(dāng)前正在執(zhí)行的effect
    const activeEffect = this.effectStack[this.effectStack.length - 1];
    if (activeEffect) {
      dep.add(activeEffect);
      // effect也需要知道哪些依賴收集了它
      activeEffect.deps.push(dep);
    }
  }

  // 觸發(fā)更新
  trigger(target, key) {
    const depsMap = this.targetMap.get(target);
    if (!depsMap) return;

    const dep = depsMap.get(key);
    if (dep) {
      // 如果是批量更新模式,加入隊列
      if (this.isBatching) {
        dep.forEach(effect => this.batchQueue.add(effect));
      } else {
        // 立即執(zhí)行所有依賴的effect
        dep.forEach(effect => {
          if (effect !== this.effectStack[this.effectStack.length - 1]) {
            effect.run();
          }
        });
      }
    }
  }

  // 創(chuàng)建effect(副作用)
  effect(fn) {
    const effect = new ReactiveEffect(fn, this);
    effect.run();

    // 返回停止函數(shù)
    const runner = effect.run.bind(effect);
    runner.effect = effect;
    runner.stop = () => effect.stop();

    return runner;
  }

  // 開始批量更新
  batchStart() {
    this.isBatching = true;
  }

  // 結(jié)束批量更新
  batchEnd() {
    this.isBatching = false;

    // 執(zhí)行隊列中的所有effect
    this.batchQueue.forEach(effect => {
      if (effect !== this.effectStack[this.effectStack.length - 1]) {
        effect.run();
      }
    });

    this.batchQueue.clear();
  }

  // computed計算屬性
  computed(getter) {
    let value;
    let dirty = true;

    const runner = this.effect(() => {
      value = getter();
      dirty = false;
    });

    return {
      get value() {
        if (dirty) {
          runner();
        }
        return value;
      }
    };
  }

  // watch偵聽器
  watch(source, callback, options = {}) {
    let getter;

    if (typeof source === 'function') {
      getter = source;
    } else {
      getter = () => this.traverse(source);
    }

    let oldValue;
    const job = () => {
      const newValue = runner();
      callback(newValue, oldValue);
      oldValue = newValue;
    };

    const runner = this.effect(getter, {
      lazy: true,
      scheduler: job
    });

    oldValue = runner();

    if (options.immediate) {
      job();
    }
  }

  // 深度遍歷對象(用于watch)
  traverse(value, seen = new Set()) {
    if (typeof value !== 'object' || value === null || seen.has(value)) {
      return value;
    }

    seen.add(value);

    for (const key in value) {
      this.traverse(value[key], seen);
    }

    return value;
  }
}

// 響應(yīng)式effect類
class ReactiveEffect {
  constructor(fn, scheduler) {
    this.fn = fn;
    this.scheduler = scheduler;
    this.deps = [];
    this.active = true;
  }

  run() {
    if (!this.active) return;

    try {
      this.scheduler.effectStack.push(this);
      return this.fn();
    } finally {
      this.scheduler.effectStack.pop();
    }
  }

  stop() {
    if (this.active) {
      // 從所有依賴中移除自己
      this.deps.forEach(dep => dep.delete(this));
      this.deps.length = 0;
      this.active = false;
    }
  }
}

實現(xiàn)不可變數(shù)據(jù)(immer.js原理)

// 簡易版immer實現(xiàn)
class Immer {
  constructor(baseState) {
    this.baseState = baseState;
    this.draft = this.createDraft(baseState);
    this.isModified = false;
  }

  // 創(chuàng)建草稿(代理)
  createDraft(base) {
    // 如果不是對象,直接返回
    if (typeof base !== 'object' || base === null) {
      return base;
    }

    // 處理數(shù)組
    if (Array.isArray(base)) {
      return this.createArrayDraft(base);
    }

    // 處理對象
    return this.createObjectDraft(base);
  }

  // 創(chuàng)建對象草稿
  createObjectDraft(base) {
    const draft = Array.isArray(base) ? [] : {};

    // 復(fù)制所有屬性
    for (const key in base) {
      if (base.hasOwnProperty(key)) {
        draft[key] = this.createDraft(base[key]);
      }
    }

    // 創(chuàng)建代理
    return new Proxy(draft, {
      get: (target, prop, receiver) => {
        // 特殊屬性處理
        if (prop === '__immer_draft__') return true;
        if (prop === '__immer_original__') return base;

        return Reflect.get(target, prop, receiver);
      },

      set: (target, prop, value, receiver) => {
        this.isModified = true;

        // 如果新值是普通值,直接設(shè)置
        if (typeof value !== 'object' || value === null) {
          return Reflect.set(target, prop, value, receiver);
        }

        // 如果新值是草稿,獲取其最終狀態(tài)
        if (value.__immer_draft__) {
          value = this.finalize(value);
        }

        // 如果新值是對象,創(chuàng)建新的草稿
        const newDraft = this.createDraft(value);
        return Reflect.set(target, prop, newDraft, receiver);
      },

      deleteProperty: (target, prop) => {
        this.isModified = true;
        return Reflect.deleteProperty(target, prop);
      }
    });
  }

  // 創(chuàng)建數(shù)組草稿(需要特殊處理)
  createArrayDraft(base) {
    const draft = this.createObjectDraft(base);

    // 代理數(shù)組方法
    const arrayMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];

    arrayMethods.forEach(method => {
      const originalMethod = Array.prototype[method];

      draft[method] = function (...args) {
        this.isModified = true;
        return originalMethod.apply(this, args);
      }.bind({ isModified: false }); // 這里簡化處理
    });

    return draft;
  }

  // 獲取草稿
  getDraft() {
    return this.draft;
  }

  // 完成修改,生成新狀態(tài)
  produce(producer) {
    // 執(zhí)行生產(chǎn)者函數(shù)
    producer(this.draft);

    // 如果沒有修改,返回原狀態(tài)
    if (!this.isModified) {
      return this.baseState;
    }

    // 最終化草稿,生成新狀態(tài)
    return this.finalize(this.draft);
  }

  // 最終化草稿(將草稿轉(zhuǎn)換為普通對象)
  finalize(draft) {
    // 如果不是草稿,直接返回
    if (!draft || !draft.__immer_draft__) {
      return draft;
    }

    const original = draft.__immer_original__;
    const result = Array.isArray(original) ? [] : {};
    let hasChanges = false;

    // 收集所有鍵(包括原對象和新對象)
    const allKeys = new Set([
      ...Object.keys(original || {}),
      ...Object.keys(draft)
    ]);

    for (const key of allKeys) {
      const originalValue = original ? original[key] : undefined;
      const draftValue = draft[key];

      // 如果屬性被刪除
      if (!(key in draft)) {
        hasChanges = true;
        continue;
      }

      // 如果值是草稿,遞歸最終化
      if (draftValue && draftValue.__immer_draft__) {
        const finalized = this.finalize(draftValue);
        if (finalized !== originalValue) {
          hasChanges = true;
          result[key] = finalized;
        } else {
          result[key] = originalValue;
        }
      }
      // 如果值被修改
      else if (draftValue !== originalValue) {
        hasChanges = true;
        result[key] = draftValue;
      }
      // 值未修改
      else {
        result[key] = originalValue;
      }
    }

    return hasChanges ? result : original;
  }
}

// 簡化API
function produce(baseState, producer) {
  const immer = new Immer(baseState);
  return immer.produce(producer);
}

結(jié)語

Proxy和Reflect開啟了JavaScript元編程的新篇章,它們不僅是框架開發(fā)的利器,也是理解現(xiàn)代JavaScript運行時特性的關(guān)鍵。

到此這篇關(guān)于JavaScript Proxy與Reflect的實現(xiàn)的文章就介紹到這了,更多相關(guān)JavaScript Proxy Reflect內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

大荔县| 包头市| 桦南县| 太湖县| 陕西省| 九龙县| 溧水县| 沂源县| 咸宁市| 冷水江市| 延吉市| 舞钢市| 阳西县| 大渡口区| 额尔古纳市| 临清市| 佛冈县| 灵丘县| 阳城县| 嘉峪关市| 青铜峡市| 合水县| 资源县| 安阳市| 赤城县| 宜兰县| 渭源县| 中西区| 永平县| 瑞昌市| 社会| 西昌市| 宿州市| 湘西| 沐川县| 界首市| 房产| 龙川县| 兴城市| 和政县| 嘉定区|