Jadual Kandungan
Apakah WeakMap
Sintaks
Kaedah
Mengapa menggunakan WeakMap dan bukannya Map
标记清除
引用计数
区别
WeakMap 应用
存储 DOM 节点
数据缓存
部署类中的私有属性
Rumah hujung hadapan web View.js Apakah WeakMap? Mengapakah ia digunakan sebagai kawasan cache dalam kod sumber responsif Vue3?

Apakah WeakMap? Mengapakah ia digunakan sebagai kawasan cache dalam kod sumber responsif Vue3?

Dec 22, 2021 am 10:19 AM
vue.js

Artikel ini akan membawa anda memahami WeakMap dalam Vue3 dan memperkenalkan sebab WeakMap digunakan sebagai "kawasan cache" dalam kod sumber responsif Vue 3. Saya harap ia akan membantu semua orang.

Apakah WeakMap? Mengapakah ia digunakan sebagai kawasan cache dalam kod sumber responsif Vue3?

[Cadangan berkaitan: "tutorial vue.js"]

Tonton sambil membaca beberapa kod prinsip responsif Vue 3 Apabila ia sedang menjalankan pemprosesan responsif, "kawasan cache" dicipta untuk setiap objek menggunakan WeakMap Kod adalah seperti berikut:

// 注意下面这句代码!
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
}
Salin selepas log masuk

Seperti yang dapat dilihat daripada kod di atas, WeakMap cache. tujuan zon adalah untuk mengelakkan objek daripada diproksi berulang kali.

Mengapa Vue 3 menggunakan WeakMap untuk cache objek proksi? Mengapa tidak menggunakan cara lain untuk cache, seperti Map?

Apakah WeakMap

WeakMap Objek ialah koleksi pasangan nilai kunci, dengan kuncinya rujukan lemah. Kekunci mestilah objek, manakala nilainya boleh sewenang-wenangnya.

Sintaks

new WeakMap([iterable])
Salin selepas log masuk

Iterable ialah tatasusunan (tatasusunan dua elemen) atau objek boleh lelar lain yang unsurnya ialah pasangan nilai kunci. Setiap pasangan nilai kunci akan ditambahkan pada WeakMap baharu.

Kaedah

WeakMap Terdapat empat kaedah: get, set, has, delete Mari kita lihat penggunaan amnya:

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
Salin selepas log masuk

Mengapa menggunakan WeakMap dan bukannya Map

Dalam JavaScript, API map boleh berkongsi dua tatasusunan (satu untuk kunci dan satu untuk nilai) melalui empat kaedah API ) untuk dicapai. Ini akan menambah kedua-dua kunci dan nilai pada penghujung kedua-dua tatasusunan apabila menetapkan nilai kepada ini map . Ini menjadikan indeks kunci dan nilai sepadan dalam dua tatasusunan. Apabila mendapat nilai daripada map ini, anda perlu mengulangi semua kekunci dan kemudian menggunakan indeks untuk mendapatkan semula nilai yang sepadan daripada tatasusunan di mana nilai itu disimpan.

Tetapi pelaksanaan sedemikian akan mempunyai dua kelemahan besar Pertama, tugasan dan operasi carian kedua-duanya mempunyai kerumitan masa O(n) (n ialah bilangan pasangan nilai kunci), kerana kedua-dua Semua ini. operasi memerlukan merentasi keseluruhan tatasusunan untuk pemadanan.

Satu lagi kelemahan ialah ia boleh menyebabkan kebocoran memori kerana tatasusunan akan sentiasa merujuk setiap kunci dan nilai. Rujukan sedemikian menghalang algoritma kutipan sampah daripada mengitar semulanya walaupun tiada rujukan lain wujud.

let jser = { name: "dachui" };

let array = [ jser ];

jser = null; // 覆盖引用
Salin selepas log masuk

Dalam kod di atas, kita meletakkan objek ke dalam tatasusunan, kemudian selagi tatasusunan itu wujud, maka objek itu juga akan wujud, walaupun tiada rujukan lain kepada objek itu .

let jser = { name: "dachui" };

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

jser = null; // 覆盖引用
Salin selepas log masuk

Begitu juga, jika kita menggunakan objek sebagai kunci untuk Map biasa, maka apabila Map wujud, objek itu juga akan wujud. Ia mengambil ingatan dan tidak akan dituntut semula oleh mekanisme kutipan sampah.

Sebaliknya, asli WeakMap memegang rujukan lemah setiap objek utama, yang bermaksud kutipan sampah boleh diteruskan dengan betul apabila tiada rujukan lain wujud.

Ia adalah kerana rujukan yang lemah yang WeakMap's key tidak dapat dikira (tiada kaedah yang boleh memberikan semua key). Jika key boleh dikira, senarainya akan dipengaruhi oleh mekanisme kutipan sampah, mengakibatkan hasil yang tidak ditentukan. Oleh itu, jika anda mahukan senarai nilai key untuk objek jenis ini, anda harus menggunakan Map.

Ringkasnya, kita boleh membuat kesimpulan berikut: Objek yang ditunjuk oleh kekunci WeakMap tidak dikira dalam mekanisme kutipan sampah .

Jadi, jika anda ingin menambah data pada objek dan tidak mahu mengganggu mekanisme kutipan sampah, anda boleh menggunakan WeakMap.

Semua orang mesti tahu selepas melihat ini, sebab Vue 3 menggunakan WeakMap sebagai penimbal adalah untuk mengumpul sampah data yang tidak lagi digunakan dengan betul.

Apakah rujukan lemah

Mengenai "rujukan lemah", Wikipedia memberikan jawapan:

Dalam pengaturcaraan komputer,
Rujukan lemah dan Rujukan yang kukuh Relatif, ia merujuk kepada rujukan yang tidak dapat memastikan objek yang dirujuk tidak akan dikitar semula oleh pemungut sampah. Objek dianggap tidak boleh diakses (atau lemah boleh diakses) jika ia dirujuk hanya oleh rujukan yang lemah, dan oleh itu boleh dikumpulkan pada bila-bila masa.
Mengapa rujukan lemah berlaku

Jadi, mengapa rujukan lemah berlaku? Selain menyelesaikan masalah di atas, apakah masalah lain yang boleh diselesaikan oleh rujukan yang lemah? Untuk menjawab soalan-soalan ini, pertama sekali kita perlu memahami bagaimana enjin

melakukan pengumpulan sampah. V8

Untuk

, pengurusan memori adalah automatik dan tidak kelihatan, semuanya terima kasih kepada enjin JSer secara senyap membantu kami mencari memori yang tidak digunakan dan membersihkannya di belakang tabir. V8

Jadi, apa yang berlaku apabila kita tidak lagi memerlukan sesuatu,

dan bagaimana enjin mencarinya dan membersihkannya? 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);
Salin selepas log masuk

上面代码中,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
Salin selepas log masuk

可以看到最后都输出 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
Salin selepas log masuk

使用 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
Salin selepas log masuk

如上,完美解决~~

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

Atas ialah kandungan terperinci Apakah WeakMap? Mengapakah ia digunakan sebagai kawasan cache dalam kod sumber responsif Vue3?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Perbincangan mendalam tentang cara vite menghurai fail .env Perbincangan mendalam tentang cara vite menghurai fail .env Jan 24, 2023 am 05:30 AM

Apabila menggunakan rangka kerja Vue untuk membangunkan projek bahagian hadapan, kami akan menggunakan berbilang persekitaran apabila digunakan Selalunya nama domain antara muka yang dipanggil oleh pembangunan, ujian dan persekitaran dalam talian adalah berbeza. Bagaimanakah kita boleh membuat perbezaan? Iaitu menggunakan pembolehubah dan corak persekitaran.

Penjelasan grafik terperinci tentang cara mengintegrasikan editor kod Ace dalam projek Vue Penjelasan grafik terperinci tentang cara mengintegrasikan editor kod Ace dalam projek Vue Apr 24, 2023 am 10:52 AM

Ace ialah editor kod boleh terbenam yang ditulis dalam JavaScript. Ia sepadan dengan fungsi dan prestasi penyunting asli seperti Sublime, Vim dan TextMate. Ia boleh dibenamkan dengan mudah ke dalam mana-mana halaman web dan aplikasi JavaScript. Ace dikekalkan sebagai editor utama untuk Cloud9 IDE dan merupakan pengganti kepada projek Mozilla Skywriter (Bespin).

Apakah perbezaan antara komponenisasi dan modularisasi dalam vue Apakah perbezaan antara komponenisasi dan modularisasi dalam vue Dec 15, 2022 pm 12:54 PM

Perbezaan antara komponenisasi dan modularisasi: Modularisasi dibahagikan dari perspektif logik kod; ia memudahkan pembangunan berlapis kod dan memastikan bahawa fungsi setiap modul berfungsi adalah konsisten. Pengkomponenan adalah perancangan dari sudut antara muka UI pemkomponenan bahagian hadapan memudahkan penggunaan semula komponen UI.

Terokai cara menulis ujian unit dalam Vue3 Terokai cara menulis ujian unit dalam Vue3 Apr 25, 2023 pm 07:41 PM

Vue.js telah menjadi rangka kerja yang sangat popular dalam pembangunan bahagian hadapan hari ini. Memandangkan Vue.js terus berkembang, ujian unit menjadi semakin penting. Hari ini kita akan meneroka cara menulis ujian unit dalam Vue.js 3 dan menyediakan beberapa amalan terbaik serta masalah dan penyelesaian biasa.

Mari kita bercakap secara mendalam tentang reactive() dalam vue3 Mari kita bercakap secara mendalam tentang reactive() dalam vue3 Jan 06, 2023 pm 09:21 PM

Kata Pengantar: Dalam pembangunan vue3, reaktif menyediakan kaedah untuk melaksanakan data responsif. Ini adalah API yang kerap digunakan dalam pembangunan harian. Dalam artikel ini, penulis akan meneroka mekanisme operasi dalamannya.

Perbandingan mudah sintaks JSX dan sintaks templat dalam Vue (analisis kelebihan dan kekurangan) Perbandingan mudah sintaks JSX dan sintaks templat dalam Vue (analisis kelebihan dan kekurangan) Mar 23, 2023 pm 07:53 PM

Dalam Vue.js, pembangun boleh menggunakan dua sintaks berbeza untuk mencipta antara muka pengguna: sintaks JSX dan sintaks templat. Kedua-dua sintaks mempunyai kelebihan dan kekurangannya sendiri Mari kita bincangkan perbezaan, kelebihan dan kekurangannya.

Analisis ringkas tentang cara mengendalikan pengecualian dalam komponen dinamik Vue3 Analisis ringkas tentang cara mengendalikan pengecualian dalam komponen dinamik Vue3 Dec 02, 2022 pm 09:11 PM

Bagaimana untuk mengendalikan pengecualian dalam komponen dinamik Vue3? Artikel berikut akan membincangkan kaedah pengendalian pengecualian komponen dinamik Vue3 Saya harap ia akan membantu semua orang.

Analisis prinsip Vue2 melaksanakan API komposisi Analisis prinsip Vue2 melaksanakan API komposisi Jan 13, 2023 am 08:30 AM

Sejak keluaran Vue3, perkataan komposisi API telah memasuki bidang penglihatan pelajar yang menulis Vue. vue/composition-api plug-in, Pelajar Vue2 juga boleh menaiki bas Seterusnya, kami akan menggunakan ref responsif dan reaktif untuk menjalankan analisis mendalam tentang cara pemalam ini mencapai perkara ini.

See all articles