検索
ホームページウェブフロントエンドVue.jsウィークマップとは何ですか? Vue3 レスポンシブ ソース コードのキャッシュ領域として使用されるのはなぜですか?

この記事では、Vue3 の WeakMap を理解し、Vue 3 のレスポンシブ ソース コードの「キャッシュ領域」として WeakMap が使用される理由を紹介します。

ウィークマップとは何ですか? Vue3 レスポンシブ ソース コードのキャッシュ領域として使用されるのはなぜですか?

[関連する推奨事項: 「vue.js チュートリアル 」]

Vue 3 の応答原理のコードを読みながら見てください。応答処理を実行している場合、WeakMap を使用してオブジェクトごとに「キャッシュ領域」が作成されます。コードは次のとおりです:

// 注意下面这句代码!
const reactiveMap = new WeakMap();

// 核心进行劫持的方法  处理 get 和 set 的逻辑
const mutableHandlers = {
    get,
    set
}

function reactive(target: object) {
    return createReactiveObject(target, mutableHandlers, reactiveMap);
}

/**
 * @description 创建响应式对象 
 * @param {Object} target 需要被代理的目标对象
 * @param {Function} baseHandlers 针对每种方式对应的不同处理函数
 * @param {Object} proxyMap WeakMap 对象
 */
function createReactiveObject(target, baseHandlers, proxyMap) {
    // 检测 target 是不是对象,不是对象直接返回,不进行代理
    if (!isObject(target)) {
        return target
    }
    const existsProxy = proxyMap.get(target);
    // 如果该对象已经被代理过了,则直接返回,不进行重复代理
    if (existsProxy) {
        return existsProxy
    }
    // 未被代理过,则创建代理对象
    const proxy = new Proxy(target,baseHandlers);
    // 缓存,避免重复代理,即避免 reactive(reactive(Object)) 的情况出现
    proxyMap.set(target,proxy); 
    return proxy
}

上記のコードからわかるように、 WeakMap キャッシュ領域の目的は、オブジェクトが繰り返しプロキシされるのを防ぐことです。

Vue 3 がプロキシ オブジェクトをキャッシュするために WeakMap を使用するのはなぜですか? Map などの他のキャッシュ方法を使用してみてはいかがでしょうか?

WeakMapとは

WeakMap オブジェクトはキーと値のペアのコレクションであり、キーは 弱い参照です。キーは objects である必要があり、値は任意です。

Syntax

new WeakMap([iterable])

Iterable は、要素がキーと値のペアである配列 (2 要素配列) またはその他の反復可能なオブジェクトです。各キーと値のペアは新しい WeakMap に追加されます。

メソッド

WeakMap 4つのメソッドがあります: getsethasdelete では、その一般的な使用法を見てみましょう:

const wm1 = new WeakMap(),
      wm2 = new WeakMap(),
      wm3 = new WeakMap();

const o1 = {},
      o2 = function() {},
      o3 = window;

wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // value 可以是任意值,包括一个对象或一个函数
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // 键和值可以是任意对象,甚至另外一个 WeakMap 对象

wm1.get(o2); // "azerty"
wm2.get(o2); // undefined,wm2 中没有 o2 这个键
wm2.get(o3); // undefined,值就是 undefined

wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (即使值是 undefined)

wm3.set(o1, 37);
wm3.get(o1); // 37

wm1.has(o1);   // true
wm1.delete(o1);
wm1.has(o1);   // false

Map の代わりに

WeakMap

を使用する理由 JavaScript では、 map API は、2 つの配列 (1 つはキー用、もう 1 つは値用) を共有する 4 つの API メソッドを通じて実装できます。このように、この map に値を設定すると、キーと値が両方の配列の末尾に同時に追加されます。これにより、キーと値のインデックスが 2 つの配列内で対応します。この map から値を取得する場合は、すべてのキーを反復処理し、インデックスを使用して、値が格納されている配列から対応する値を取得する必要があります。

しかし、そのような実装には 2 つの大きな欠点があります。まず、代入および検索操作の時間計算量は O(n) (n はキー番号です) です。両方の操作で一致するには配列全体を走査する必要があるためです。

もう 1 つの欠点は、配列が常に各キーと値を参照するため、メモリ リークが発生する可能性があることです。このような参照は、たとえ他に参照が存在しない場合でも、ガベージ コレクション アルゴリズムによるリサイクルを妨げます。

let jser = { name: "dachui" };

let array = [ jser ];

jser = null; // 覆盖引用

上記のコードでは、オブジェクトを配列に配置します。その後、配列が存在する限り、オブジェクトへの参照が他にない場合でも、オブジェクトも存在します## #。

let jser = { name: "dachui" };

let map = new Map();
map.set(jser, "");

jser = null; // 覆盖引用
同様に、オブジェクトを通常の Map

のキーとして使用する場合、そのオブジェクトは

Map が存在するときに存在します。これはメモリを占有し、ガベージ コレクション メカニズムによって再利用されません。 対照的に、ネイティブの WeakMap

は各キー オブジェクトの

弱い参照を保持します。これは、ガベージ コレクションが正しく実行できることを意味します。 まさにこのような弱参照のため、 WeakMap

key は列挙可能ではありません (すべての key を指定できるメソッドはありません)。 key が列挙可能な場合、そのリストはガベージ コレクション メカニズムの影響を受けるため、結果は未定義になります。したがって、このタイプのオブジェクトの key 値のリストが必要な場合は、Map を使用する必要があります。 要約すると、次の結論を導き出すことができます: WeakMap のキーが指すオブジェクトは、ガベージ コレクション メカニズムではカウントされません

したがって、オブジェクトにデータを追加し、ガベージ コレクション メカニズムに干渉したくない場合は、WeakMap

を使用できます。

これを見れば誰もがわかるはずですが、Vue 3 が WeakMap

をバッファとして使用する理由は、使用されなくなったデータを正しくガベージ コレクションするためです

弱参照とは 「弱参照」については、Wikipedia に次のような答えがあります:

コンピューター プログラミングでは、

弱い参照

強力な参照
相対。参照するオブジェクトがガベージ コレクターによってリサイクルされないことを保証できない参照を指します。オブジェクトが弱い参照によってのみ参照されている場合、そのオブジェクトはアクセスできない (または弱いアクセス可能である) とみなされ、したがって はいつでもリサイクルされる可能性があります なぜ弱い参照が現れるのですか?それでは、なぜ弱い参照が現れるのでしょうか?上記の問題の解決に加えて、弱い参照によって他にどのような問題が解決できるでしょうか?これらの質問に答えるには、まず
V8

エンジンがガベージ コレクションを実行する方法を理解する必要があります。

JSer の場合、メモリ管理は自動的に行われ、目に見えません。これはすべて、

V8

エンジンがバックグラウンドで使用する必要のないファイルを自動的に見つけてくれるおかげです。 . メモリを削除してクリーンアップします。 それでは、何かが必要なくなったとき、V8 エンジンはどのようにしてそれを見つけてクリーンアップするのでしょうか?

现在各大浏览器通常用采用的垃圾回收有两种方法,一种是「引用计数」,另外一种就是「标记清除」。下面我们来看一下:

标记清除

标记清除被称为 mark-and-sweep,它是基于 可达性 来判断对象是否存活的,它会定期执行以下「垃圾回收」步骤:

  • 垃圾收集器找到所有的根,并标记(记住)它们。

  • 然后它遍历并标记来自它们的所有引用。所有被遍历到的对象都会被记住,以免将来再次遍历到同一个对象。

  • ……如此操作,直到所有可达的(从根部)引用都被访问到。

  • 没有被标记的对象都会被删除。

我们还可以将这个过程想象成从根溢出一个巨大的油漆桶,它流经所有引用并标记所有可到达的对象,然后移除未标记的。

引用计数

引用计数方式最基本的形态就是让每个被管理的对象与一个引用计数器关联在一起,该计数器记录着该对象当前被引用的次数,每当创建一个新的引用指向该对象时其计数器就加 1,每当指向该对象的引用失效时计数器就减 1。当该计数器的值降到 0 就认为对象死亡。

区别

引用计数与基于「可达性」的标记清除的内存管理方式最大的区别就是,前者只需要 局部的信息,而后者需要 全局的信息

在引用计数中每个计数器只记录了其对应对象的局部信息 —— 被引用的次数,而没有(也不需要)一份全局的对象图的生死信息。

由于只维护局部信息,所以不需要扫描全局对象图就可以识别并释放死对象。但也因为缺乏全局对象图信息,所以 无法处理循环引用 的状况。

所以,更高级的引用计数实现会引入 弱引用 的概念来打破某些已知的循环引用。

WeakMap 应用

存储 DOM 节点

WeakMap 应用的典型场合就是以 DOM 节点作为键名。下面是一个例子。

const myWeakmap = newWeakMap();
myWeakmap.set(
  document.getElementById('logo'),
  { timesClicked: 0 },
);
document.getElementById('logo').addEventListener('click', () => {
  const logoData = myWeakmap.get(document.getElementById('logo'));
  logoData.timesClicked++;
}, false);

上面代码中,document.getElementById('logo') 是一个 DOM 节点,每当发生 click 事件,就更新一下状态。我们将这个状态作为值放在 WeakMap 里,对应的键就是这个节点对象。一旦这个 DOM 节点删除,该状态就会自动消失,不存在内存泄漏风险。

数据缓存

谜底就在谜面上,文章一开头我们提出的问题就是这里的答案。Vue 3 在实现响应式原理的时候就是使用了 WeakMap 来作为响应式对象的「缓存区」。

关于这一点用法也很简单,当我们需要关联对象和数据,比如在不修改原有对象的情况下储存某些属性或者根据对象储存一些计算的值等,而又不想手动去管理这些内存问题的时候就可以使用 WeakMap

部署类中的私有属性

WeakMap 的另一个用处是部署类中的私有属性。

值得一提的是,TypeScript 中已经实现的 private 私有属性原理就是利用 WeakMap

私有属性应该是不能被外界访问到,不能被多个实例共享,JavaScript 中约定俗成地使用下划线来标记私有属性和方法,一定程度来说是不靠谱的。

下面我们用三种方法来实现:

  • 版本一:闭包
const testFn = (function () {
  let data;

  class Test {
    constructor(val) {
      data = val
    }
    getData() {
      return data;
    }
  }
  return Test;
})();

let test1 = new testFn(3);
let test2 = new testFn(4);
console.log(test1.getData()); // 4
console.log(test2.getData()); // 4

可以看到最后都输出 4,多实例共享私有属性了,所以版本一不符合。

  • 版本二:Symbol
const testFn = (function () {
  let data = Symbol('data')

  class Test {
    constructor(val) {
      this[data] = val
    }
    getData() {
      return this[data]
    }
  }
  return Test;
})();

let test1 = new testFn(3);
let test2 = new testFn(4);
console.log(test1.getData()); // 3
console.log(test2.getData()); // 4

console.log(test1[Object.getOwnPropertySymbols(test1)[0]]); // 3
console.log(test2[Object.getOwnPropertySymbols(test2)[0]]); // 4

使用 Symbol 虽然实现了而且正确输出了 34,但是我们发现可以在外界不通过 getData 方法直接拿到私有属性,所以这种方法也不满足我们的要求。

  • 版本三:WeakMap
const testFn = (function () {
  let data = new WeakMap()

  class Test {
    constructor(val) {
      data.set(this, val)
    }
    getData() {
      return data.get(this)
    }
  }
  return Test;
})();

let test1 = new testFn(3);
let test2 = new testFn(4);
console.log(test1.getData()); // 3
console.log(test2.getData()); // 4

如上,完美解决~~

更多编程相关知识,请访问:编程入门!!

以上がウィークマップとは何ですか? Vue3 レスポンシブ ソース コードのキャッシュ領域として使用されるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事はsegmentfaultで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
vue.jsとフロントエンドスタック:接続の理解vue.jsとフロントエンドスタック:接続の理解Apr 24, 2025 am 12:19 AM

VUE.JSは、開発効率とユーザーエクスペリエンスを向上させるために、フロントエンドテクノロジースタックと密接に統合されています。 1)建設ツール:Webpackおよびロールアップと統合して、モジュール開発を実現します。 2)国家管理:VUEXと統合して、複雑なアプリケーションステータスを管理します。 3)ルーティング:Vuerouterと統合して、単一ページのアプリケーションルーティングを実現します。 4)CSSプリプロセッサ:SASSをサポートし、スタイル開発効率を改善するために少なくなります。

Netflix:React(またはその他のフレームワーク)の使用の調査Netflix:React(またはその他のフレームワーク)の使用の調査Apr 23, 2025 am 12:02 AM

Netflixは、Reactのコンポーネント設計と仮想DOMメカニズムが複雑なインターフェイスと頻繁な更新を効率的に処理できるため、ユーザーインターフェイスを構築するためにReactを選択しました。 1)コンポーネントベースの設計により、Netflixはインターフェイスを管理可能なウィジェットに分解し、開発効率とコード保守性を向上させることができます。 2)仮想DOMメカニズムは、DOM操作を最小化することにより、Netflixユーザーインターフェイスの滑らかさと高性能を保証します。

vue.jsとフロントエンド:フレームワークに深く飛び込むvue.jsとフロントエンド:フレームワークに深く飛び込むApr 22, 2025 am 12:04 AM

Vue.jsは、使いやすく強力なため、開発者に愛されています。 1)そのレスポンシブデータバインディングシステムは、ビューを自動的に更新します。 2)コンポーネントシステムは、コードの再利用性と保守性を向上させます。 3)コンピューティングプロパティとリスナーは、コードの読みやすさとパフォーマンスを向上させます。 4)Vuedevtoolsの使用とコンソールエラーのチェックは、一般的なデバッグ手法です。 5)パフォーマンスの最適化には、主要な属性、計算された属性、およびキープアライブコンポーネントの使用が含まれます。 6)ベストプラクティスには、クリアコンポーネントの命名、単一ファイルコンポーネントの使用、ライフサイクルフックの合理的な使用が含まれます。

フロントエンドのvue.jsの力:主要な機能と利点フロントエンドのvue.jsの力:主要な機能と利点Apr 21, 2025 am 12:07 AM

Vue.jsは、効率的で保守可能なフロントエンドアプリケーションを構築するのに適した進歩的なJavaScriptフレームワークです。その主な機能には、1。レスポンシブデータバインディング、2。コンポーネント開発、3。仮想DOM。これらの機能を通じて、VUE.JSは開発プロセスを簡素化し、アプリケーションのパフォーマンスと保守性を向上させ、最新のWeb開発で非常に人気を博しています。

Vue.jsはReactよりも優れていますか?Vue.jsはReactよりも優れていますか?Apr 20, 2025 am 12:05 AM

Vue.jsとReactにはそれぞれ独自の利点と欠点があり、選択はプロジェクトの要件とチームの条件に依存します。 1)Vue.jsは、シンプルで使いやすいため、小さなプロジェクトや初心者に適しています。 2)Reactは、その豊富な生態系とコンポーネント設計のため、大規模なプロジェクトと複雑なUIに適しています。

Vue.jsの関数:フロントエンドでのユーザーエクスペリエンスの強化Vue.jsの関数:フロントエンドでのユーザーエクスペリエンスの強化Apr 19, 2025 am 12:13 AM

Vue.jsは複数の機能を介してユーザーエクスペリエンスを改善します。1。レスポンシブシステムは、リアルタイムデータフィードバックを実現します。 2。コンポーネント開発により、コードの再利用性が向上します。 3. Vuerouterはスムーズなナビゲーションを提供します。 4.動的データの結合および遷移アニメーションは、相互作用効果を強化します。 5.エラー処理メカニズムにより、ユーザーのフィードバックが保証されます。 6.パフォーマンスの最適化とベストプラクティスは、アプリケーションのパフォーマンスを改善します。

Vue.js:Web開発におけるその役割を定義しますVue.js:Web開発におけるその役割を定義しますApr 18, 2025 am 12:07 AM

Web開発におけるVue.jsの役割は、開発プロセスを簡素化し、効率を向上させるプログレッシブJavaScriptフレームワークとして機能することです。 1)開発者は、レスポンシブデータのバインディングとコンポーネント開発を通じてビジネスロジックに集中できるようになります。 2)VUE.JSの作業原則は、パフォーマンスを最適化するためにレスポンシブシステムと仮想DOMに依存しています。 3)実際のプロジェクトでは、VUEXを使用してグローバルな状態を管理し、データの応答性を最適化することが一般的な慣行です。

Vue.jsの理解:主にフロントエンドフレームワークVue.jsの理解:主にフロントエンドフレームワークApr 17, 2025 am 12:20 AM

Vue.jsは、2014年にYou YuxiがリリースしたプログレッシブJavaScriptフレームワークで、ユーザーインターフェイスを構築します。その中心的な利点には、次のものが含まれます。1。レスポンシブデータバインディング、データ変更の自動更新ビュー。 2。コンポーネントの開発では、UIは独立した再利用可能なコンポーネントに分割できます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター