惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Project Zero
Project Zero
F
Fortinet All Blogs
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
S
SegmentFault 最新的问题
Blog — PlanetScale
Blog — PlanetScale
T
Tailwind CSS Blog
WordPress大学
WordPress大学
Engineering at Meta
Engineering at Meta
S
Schneier on Security
N
News and Events Feed by Topic
N
News | PayPal Newsroom
H
Help Net Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
The Exploit Database - CXSecurity.com
Attack and Defense Labs
Attack and Defense Labs
博客园 - Franky
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
A
About on SuperTechFans
AWS News Blog
AWS News Blog
S
Secure Thoughts
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
爱范儿
爱范儿
C
Cybersecurity and Infrastructure Security Agency CISA
V2EX - 技术
V2EX - 技术
Recorded Future
Recorded Future
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
人人都是产品经理
人人都是产品经理
Latest news
Latest news
C
Cyber Attacks, Cyber Crime and Cyber Security
大猫的无限游戏
大猫的无限游戏
The Last Watchdog
The Last Watchdog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
月光博客
月光博客
H
Hacker News: Front Page
P
Proofpoint News Feed
N
News and Events Feed by Topic
H
Heimdal Security Blog
L
Lohrmann on Cybersecurity
有赞技术团队
有赞技术团队
L
LangChain Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活 翻译 – CSS Sprites:实用技术还是生厌之物? « 张鑫旭-鑫空间-鑫生活 纯CSS实现易拉罐3D滚动效果 « 张鑫旭-鑫空间-鑫生活 纯CSS实现侧边栏/分栏高度自动相等 « 张鑫旭-鑫空间-鑫生活 CSS+JavaScript实现页面不同布局的切换 « 张鑫旭-鑫空间-鑫生活 JavaScript实现最简单的拖拽效果 « 张鑫旭-鑫空间-鑫生活 自己写的无图片版jQuery zxxbox弹出框插件 « 张鑫旭-鑫空间-鑫生活 中国古代道家思想与网页重构的思考 « 张鑫旭-鑫空间-鑫生活 让所有浏览器支持HTML5 video视频标签 « 张鑫旭-鑫空间-鑫生活 纯CSS实现各类气球泡泡对话框效果 « 张鑫旭-鑫空间-鑫生活 JS HEX十六进制与RGB, HSL颜色的相互转换 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变、高光等文字效果 « 张鑫旭-鑫空间-鑫生活 去除冗余 – 精简您的CSS样式代码 « 张鑫旭-鑫空间-鑫生活 对overflow与zoom”清除浮动”的一些认识 « 张鑫旭-鑫空间-鑫生活 jQuery Pagination Ajax分页插件中文详解 « 张鑫旭-鑫空间-鑫生活 absolute绝对定位的非绝对定位用法 « 张鑫旭-鑫空间-鑫生活 网页布局思想浅议-淘宝新版首页为实例 « 张鑫旭-鑫空间-鑫生活 回流与重绘:CSS性能让JavaScript变慢? « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(二) « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(一) « 张鑫旭-鑫空间-鑫生活 60个极富创造性的震撼的电影海报设计 « 张鑫旭-鑫空间-鑫生活 jQuery Lightbox(balupton版)图片展示插件讲解 « 张鑫旭-鑫空间-鑫生活 博客内嵌flash音乐播放器代码、下载与使用 « 张鑫旭-鑫空间-鑫生活 CSS3 animate实现图片墙3D翻转效果 « 张鑫旭-鑫空间-鑫生活 图片旋转效果的一些研究、jQuery插件及实例 « 张鑫旭-鑫空间-鑫生活 CSS3 border-image详解、应用及jQuery插件 « 张鑫旭-鑫空间-鑫生活 jQuery-两款不同原理的圆角插件讲解 « 张鑫旭-鑫空间-鑫生活 页面可用性之outline轮廓外框的一些研究 « 张鑫旭-鑫空间-鑫生活 CSS3 transition实现超酷图片墙动画效果 « 张鑫旭-鑫空间-鑫生活 HTML CSS列表元素ul,ol,dl的研究与应用 « 张鑫旭-鑫空间-鑫生活 jQuery图片文本滚动切换插件jCarousel中文翻译与详解 « 张鑫旭-鑫空间-鑫生活 酷酷的jQuery鼠标悬停图片放大切换显示效果 « 张鑫旭-鑫空间-鑫生活 IE6下z-index犯癫不起作用bug的初步研究 « 张鑫旭-鑫空间-鑫生活 checkbox复选框的一些深入研究与理解 « 张鑫旭-鑫空间-鑫生活 jQuery之使用slideToggle实现垂直下拉菜单 « 张鑫旭-鑫空间-鑫生活 jQuery-innerfade内部列表自动淡入淡出插件 « 张鑫旭-鑫空间-鑫生活 jQuery-火焰灯效果导航菜单 « 张鑫旭-鑫空间-鑫生活 IE下css bug集合-翻译自haslayout.net « 张鑫旭-鑫空间-鑫生活 翻译-IE7/8@font-face嵌入字体与文字平滑 « 张鑫旭-鑫空间-鑫生活 jQuery-马化腾产品设计与用户体验的一些技术实现 « 张鑫旭-鑫空间-鑫生活 像素的世界及其在web开发制作中的应用 « 张鑫旭-鑫空间-鑫生活 css行高line-height的一些深入理解及应用 « 张鑫旭-鑫空间-鑫生活 CSS实现圆角六色渐变自适应按钮详解 « 张鑫旭-鑫空间-鑫生活 我熟知的三种三栏网页宽度自适应布局方法 « 张鑫旭-鑫空间-鑫生活 jQuery照片图像剪裁插件Jcrop中文翻译详解 « 张鑫旭-鑫空间-鑫生活 Ajax Upload多文件上传插件翻译及中文演示 « 张鑫旭-鑫空间-鑫生活 告别图片—使用字符实现兼容性的圆角尖角效果beta版 « 张鑫旭-鑫空间-鑫生活 大小不固定的图片、多行文字的水平垂直居中 « 张鑫旭-鑫空间-鑫生活 jQuery boxy弹出层对话框插件中文演示及讲解 « 张鑫旭-鑫空间-鑫生活 JavaScript实现新浪微博文字放大显示动画效果 « 张鑫旭-鑫空间-鑫生活 翻译:让网络更快一些——最小化浏览器中的回流(reflow) « 张鑫旭-鑫空间-鑫生活 jQuery之addClasas与removeClass使用实例 « 张鑫旭-鑫空间-鑫生活 关于Google圆角高光高宽自适应按钮及其拓展 « 张鑫旭-鑫空间-鑫生活 JavaScript实现图片幻灯片滚动播放动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery-鼠标经过显示大图并跟随鼠标效果插件 « 张鑫旭-鑫空间-鑫生活 关于gif图片(或png8)杂边锯齿的问题 « 张鑫旭-鑫空间-鑫生活 对html与body的一些研究与理解 « 张鑫旭-鑫空间-鑫生活 鲜为人知的一个解决兼容性问题的利器——小数 « 张鑫旭-鑫空间-鑫生活 搜狐白社会似iphone短信对话框效果的优化 « 张鑫旭-鑫空间-鑫生活 关于文字内容溢出用点点点(…)省略号表示 « 张鑫旭-鑫空间-鑫生活 jquery之append与insertBefore使用实例 « 张鑫旭-鑫空间-鑫生活 jQuery之图片关联伸缩效果 « 张鑫旭-鑫空间-鑫生活 jquery之图片左右切换动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery之replace字符串替换实现不同尺寸图片切换 « 张鑫旭-鑫空间-鑫生活 jQuery-实现图片的放大镜显示效果 « 张鑫旭-鑫空间-鑫生活 jQuery-单击文字或图片内容放大显示效果插件 « 张鑫旭-鑫空间-鑫生活 reflection.js-实现图片投影倒影效果js插件 « 张鑫旭-鑫空间-鑫生活 jQuery-很酷的弹出层效果js插件 « 张鑫旭-鑫空间-鑫生活 复选框单选框与文字对齐问题的研究与解决 « 张鑫旭-鑫空间-鑫生活 css margin的相关属性,问题及应用 « 张鑫旭-鑫空间-鑫生活 IE6下png背景不透明问题的综合拓展 « 张鑫旭-鑫空间-鑫生活
JS WeakMap应该什么时候使用 « 张鑫旭-鑫空间-鑫生活
张鑫旭,zhangxinxu · 2021-08-15 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10064 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

红梅葡萄占位图

一、从哪里开始呢?

算了,还是先说结论吧。

二、WeakMap什么时候用?

首先,大家要明白,就算没有 WeakMap,JS的世界也是照常运转,WeakMap在JS世界的地位,就和其名称一样——“weak”,弱。

属于那种有作用,但是并不在关键位置干大事的人,有点类似于一些CSS功能选择器,虽然使用更简单更方便,但是平常使用JS实现的交互效果挺好的,所以并不那么流行与普及。

WeakMap的作用就是可以更有效的垃圾回收、释放内存。

我们平常开发的Web应用都是如此的简单,就算代码很垃圾,吃了很多内存那又如何,页面照样流畅,用户照样无感知。

所以,对于绝大多数开发者和应用程序而言,WeakMap的商业价值是很低的。

这么一说,似乎WeakMap没什么好学的。

其实不然。

如果是超大型应用,或者用户基数庞大的产品,或者是服务器这种负载较高的场景,对于内存管理要求就很高,此时WeakMap的优势就可以体现。

这其实有点悖论的味道在里面。

上述所有需要用到WeakMap的场景都一定是需要资深前端开发参与的场景,而如果你连WeakMap都不知道,就谈不上资深,挑上面的大梁可能会闪着腰。

也就是,你学会了WeakMap以及类似的JS知识点,才有机会参与必须要使用这些JS特性的项目中,完成自我价值的证明与贡献。

所以,没有什么知识是没用的,只是时机的问题,所谓厚积薄发,就是这样一个意思。

垃圾?内存?

就内存管理而言,JS开发人员可以归为下面几种:

  1. 内存?什么内存?我JS想怎么写就怎么写,运行不挺好的!反正浏览器页面关掉什么都没了。
  2. 恩,这里这个对象之后没用了,我可以设置为null。意识是好的,设置也设置了,就是内存究竟有没有释放不得而知,看运气。
  3. 这里设置null不行,因为对象在其他地方也引用了,其他引用的地方也要删除,属于理解比较深刻的,JS基本功很扎实的。

举个大家比较容易懂的例子,已知页面中有个DOM元素,HTML结构如下:

<img id="img" src="https://bookcover.yuewen.com/qdbimg/349573/1027030348/180">

然后,需要删除此DOM元素,小明是这么处理的:

var eleImage = document.getElementById('img');
eleImage.remove();

这个处理有没有什么问题?

从效果上来看,完全解决了需求。

但是实际上,虽然页面中的图片元素删除了,但是内存中的这个DOM对象依然存在的。

我们不妨这样测试下:

var eleImage = document.getElementById('img');
eleImage.remove();

setTimeout(() => {
  document.body.append(eleImage);
}, 2000);

就会看到图片被删除了(如下GIF录屏),然后过了2秒钟又出现在了页面上,因为eleImage还在内存中,并未清除,不会被回收。

删除后2秒又出现

所以,如果确定eleImage不再需要,需要多执行一句,同时设为 null。

var eleImage = document.getElementById('img');
eleImage.remove();
eleImage = null;

这样,JS在执行垃圾回收的时候,就会把eleImage这个垃圾收回,释放内存。

大家可以看看自己是不关心内存的那类JS开发,还是会注意释放不需要的内存的JS开发。

OK,事情还没完,有时候,设置eleImage为null,并不能真正回收内存。

例如实际开发,有时候需要记住初始的outerHTML字符,方便还原。为了和原始DOM产生关联,有些开发就把DOM元素和outerHTML字符串放在同一个数组中进行管理:

var eleImage = document.getElementById('img');
var storage = {
    arrDom: [eleImage, eleImage.outerHTML]
};
eleImage.remove();
eleImage = null;

此时,eleImage这个DOM对象其实还在内存中。因为 eleImage 被 storage.arrDom 引用了,即使eleImage设为null也无法将内存彻底释放。

测试下:

var eleImage = document.getElementById('img');
var storage = {
    arrDom: [eleImage, eleImage.outerHTML]
};
eleImage.remove();
eleImage = null;

setTimeout(() => {
  document.body.append(storage.arrDom[0]);
}, 2000);

同样可以看到,图片被删除后,2秒后又出现了。

这个还是看实时效果吧。

点击后面的按钮查看效果:

此时,要想完全把图像的内存释放,还需要执行下面这行:

storage.arrDom[0] = null;

大家试想下,如果是你,可以释放内存做到这一步吗?如果可以做到,那你就可以归类为资深的JS前端开发那一类了。

但是,纯靠技术手段,人工识别哪些地方的内存要释放,实在是太累了。就算懂行的人有时候嫌麻烦,都懒得去管理,那有没有什么手段,我只要变量设为null,所有有引用的地方的内存都自动释放呢?

这就可以考虑使用WeakMap了。

//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=10064(作者张鑫旭)

使用场景

上面的例子,如果使用WeakMap实现回是怎样的呢?

代码说话:

var eleImage = document.getElementById('img');
var storeMap = new WeakMap();
storeMap.set(eleImage, eleImage.outerHTML);
eleImage.remove();
eleImage = null;

同样是缓存图片的outerHTML数据,但是这里使用了 WeakMap 对象,将 eleImage 作为一个弱键,这样,eleImage一旦设置为 null,所有相关的数据都会被释放。

究竟内存释放没有,上面的例子不好测试,一是要借助工具,二是内存变化很小,看不出来。

更新于当日
经过评论反馈,FinalizationRegistry是可以检测垃圾回收的执行,并触发相应的回调的。

不过,我们可以使用Map对象对比下,如果是Map对象,eleImage作为键,那就是强引用,是一直在内存中的,例如:

var eleImage = document.getElementById('img');
var storeMap = new Map();
storeMap.set(eleImage, eleImage.outerHTML);
eleImage.remove();
eleImage = null;

setTimeout(() => {
  document.body.append(storeMap.keys().next().value);
}, 2000);

可以看到,虽然eleImage remove掉了,还设为了null,但是依然在内存中,可以append到页面中。

根据上面的分析和描述,我们可以得出下面的结论。

结论

当我们需要在某个对象上临时存放数据的时候,请使用WeakMap,尤其对于JS理解不是很深刻的开发人员,更是如此,因为省心,不要关心经常挂在嘴边的“内存泄露”问题。

因为到时候只需要删除该对象,所有相关的引用和关联的内存都会被释放。

也就是,虽然我看不懂代码是怎么执行的,但是我这么写的,性能就是好,逼格就是高!

看不懂

三、回到WeakMap语法本身

说了这么多,是时候介绍 WeakMap 语法的真身了。

语法

let myWm = new WeakMap()

此时,myWm就是一个新的WeakMap对象,包括了下面这些方法:

// 删除键
myWm.delete(key);
// 设置键和值
myWm.set(key, value);
// 是否包含某键
myWm.has(key);
// 获取键对应的值
myWm.get(key);

说明

  1. key只能是对象,不能是原始数据类型(字符串、数字、true或false,null,undefined,symbol等类型)
  2. WeakMap中的键是无法枚举的

key只能是对象

下面的用法都是可以的:

myWm.set([], 1);
myWm.set(new Date(), '鑫空间');
myWm.set(()=>{}, 1);
myWm.set(document.createElement('by-zhangxinxu'), 1);

但是如果key不是对象,而是字符串之类的基本类型,就会报错,例如:

// 会报错
myWm.set('css新世界', true);

此时会报下面的错误:

“TypeError: Invalid value used as weak map key

因此WeakMap适合用在在对象上临时缓存数据的场景。

key无法枚举

不同于Map对象,Map对象是可以枚举的,有keys()values()entries()方法,还可以使用forEach遍历。

但是WeakMap无法枚举,WeakMap的这个特性也可以用来模拟私有属性。

const myWm = new WeakMap();
class Fish {
    constructor(name) {
        myWm.set(this, { 
            _fishbone: ['草鱼', '鲫鱼', '青鱼', '鲤鱼', '鲢鱼', '鳙鱼', '鳊鱼', '翘嘴', '餐条'],
        });
        this.name = name;
    }

    isBone() {
        return myWm.get(this)._fishbone.includes(this.name);
    }
}

// 测试,买了两条鱼
let fish1 = new Fish('草鱼');
let fish2 = new Fish('回鱼');

// 返回 true,有刺
console.log(fish1.isBone());
// 返回 false,没有肌间刺
console.log(fish2.isBone());

上面的代码中,_fishbone虽然和Fish对象相关联,但是却无法通过Fish对象直接获取。

如果不知道名称,也无法通过myWm遍历出来。

关于WeakMap更详细的语法介绍和示意可参考MDN文档:MDN WeakMap

四、结束语

考考大家,我昨天钓的下面3种鱼,哪种鱼有肌间刺,哪几种鱼没有肌间刺?

钓货

好,本文内容就上面这些。

如果文中有表述不准确的地方,或者有所遗漏,欢迎指正。

如果您觉得文章不错,也欢迎分享。

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=10064

(本篇完)