MoreRSS

site iconZhangXinXu | 张鑫旭修改

出版《CSS选择器世界》,喜欢钓鱼、写作。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

ZhangXinXu | 张鑫旭的 RSS 预览

CSS @supports规则又新增font-tech,font-format判断

2025-03-09 21:11:08

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11531
本文可全文转载,独立域名个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。

封面占位图

继续关注Web前端前沿新特性,这次快速介绍CSS @supports规则新增加的两个特性判断,一个是font-tech(),另外一个是font-format()函数,都来看看是什么作用吧。

一、font-tech()的功能

font-tech()函数可以检查浏览器是否支持用于布局和渲染的指定字体技术。

例如,下面这段CSS代码可以判断浏览器是否支持COLRv1字体(一种彩色字体技术)技术。

@supports font-tech(color-COLRv1) {}

下表展示了可以作为font-tech()函数的参数,数据源自MDN文档。

5年前的这篇文章“关于CSS emoji字体和OpenType-SVG我所知道的一些事”对其中一些字体技术有过简单的介绍,有兴趣的可以了解下。

技术 描述
彩色字体技术
color-colrv0 COLR 版本 0 彩色字体
color-colrv1 COLR 版本 1 彩色字体
color-svg SVG 彩色字体
color-sbix 标准位图图形字体
color-cbdt 彩色位图数据
字体特征技术
features-opentype OpenType GSUB 以及 GPOS技术
features-aat TrueType morx 以及 kerx 技术
features-graphite 石墨特征,即 Silf, Glat, Gloc, Feat 以及 Sill
其他字体技术值
incremental-patch 使用补丁子集方法进行增量字体加载
incremental-range 使用范围请求方法增量加载字体
incremental-auto 使用自动协商方法的增量字体加载
variations TrueType和OpenType字体中的字体变化,用于控制字体轴、粗细、字形等。
palettes 字体调色板技术,也就是通过font-palttle选择字体中的许多调色板之一

二、font-format()的作用

font-format()这个比较好理解,是检测浏览器是否支持制定的字体格式的。

同样支持的参数值和对应的字体格式如下表所示:

格式 描述 文件后缀
collection OpenType集合 .otc, .ttc
embedded-opentype 嵌入式OpenType .eot
opentype OpenType .ttf, .otf
svg SVG字体 (已废弃) .svg, .svgz
truetype TrueType .ttf
woff WOFF 1.0 (Web Open Font Format) .woff
woff2 WOFF 2.0 (Web Open Font Format) .woff2

使用示意:

@supports font-format(woff2) {
  /* 浏览器支持woff2字体 */
}

三、鑫辣点评这两个特性

好,这两个字体相关的检测函数算是介绍完了,下面过来点评下。

直接说结论:没用的废物特性!

但两者的废物之处各有不同。

font-tech()是检测字体技术的,这个对于中文场景就是鸡肋特性,因为中文字体是不会使用这类技术的,无他,成本太高。

英文字体就一些字母和数字,你里面搞彩色字体,变体之类的,成本是可控的。

但是中文字体,少说几千个,里面再造字体特征,变形之类的,是多么浩大的工程,所以,目前业界,至少到现在为止,我是没有看到一块有彩色字体或者字体特征的中文字体的,日文字体倒是有。

font-format()函数的问题在于出现的太晚了。

例如woff2字体的检测,这个所有现代浏览器都已经支持了,还有检测的必要吗,没了,没有意义了,就好像都已经射完了,才从抽屉里翻出一个套。

所以啊,大家看看,了解下有这么个东西就好了。

但是,如果抛开其原本作用……

CSS这门语言很神奇,就是很多CSS属性大行其道并不是因为其原本的设计初衷,而是其衍生的特性。

所以,这里这两个函数,如果抛开其原本作用,倒不是没有价值可言。

例如,我们可以利用此函数判断当前浏览器是不是Safari浏览器,例如color-colrv1彩色字体技术Safari是不支持的,我们可以借此判断当前浏览器。

@supports not font-tech(color-COLRv1) {
  /* Safari浏览器 */
}

兼容性截图示意:

v1算法兼容性

是不是还挺有趣的?

好,就扯这么多。

🥱😴🤤

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11531

(本篇完)

终于等到了,CSS offset-path全浏览器全支持

2025-03-05 22:36:07

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11536
本文可全文转载,独立域名个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。

封面占位图 offset-path

一、历史与发展

CSS offset-path属性其实在8年前就介绍过了,参见:“使用CSS offset-path让元素沿着不规则路径运动

不过那个时候的offset-path属性只支持不规则路径,也就是path()函数,很多CSS关键字,还有基本形状是不支持的。

终于,盼星星盼月亮。

从Safari 18开始,CSS offset-path属性所有现代浏览器全面支持了。

浏览器兼容性截图如下所示:

offset-path兼容性

二、offset-path的作用

offset-path可以用来实现各类炫酷的路径动画效果。

举几个简单的例子。

比方说,蚂蚁🐜绕圈圈的动画,找一个蚂蚁的GIF动图,然后使用circle()函数就可以了,相关的HTML和CSS代码如下所示:

><div class="shape">
    <i class="ant"></i>
</div>
.shape {
    width: 150px; height: 150px;
    border: 2px dashed darkgray;
    border-radius: 50%;
}
.ant {
    display: block;
    width: 30px; height: 42px;
    background: url(./ant-walk-s.gif) no-repeat center/ contain;
    offset-path: circle(75px);
    animation: offset 3s linear infinite;
    transform: rotate(90deg);
}
@keyframes offset {
  to {
    offset-distance: 100%;
  }
}

此时,便可以看到如下GIF录屏所示的动效了。

蚂蚁绕圈GIf

眼见为实,您可以狠狠地点击这里:CSS offset-path属性实现蚂蚁绕圈动画demo

三、offset-path的语法与说明

offset-path属性的语法还比较复杂,不过很多大家都用不到。

/* 默认*/
offset-path: none;

/* 线段 */
offset-path: ray(45deg closest-side contain);
offset-path: ray(contain 150deg at center center);
offset-path: ray(45deg);

/* URL路径,这个很早就支持了 */
offset-path: url(#myCircle);

/* 基本形状,最近刚支持 */
offset-path: circle(50% at 25% 25%);
offset-path: ellipse(50% 50% at 25% 25%);
offset-path: inset(50% 50% 50% 50%);
offset-path: polygon(30% 0%, 70% 0%, 100% 50%, 30% 100%, 0% 70%, 0% 30%);
offset-path: path("M 0,200 Q 200,200 260,80 Q 290,20 400,0 Q 300,100 400,200");
offset-path: rect(5px 5px 160px 145px round 20%);
offset-path: xywh(0 5px 100% 75% round 15% 0);

/* 坐标盒子,其中后三个值用在SVG元素中 */
offset-path: content-box;
offset-path: padding-box;
offset-path: border-box;
offset-path: fill-box;
offset-path: stroke-box;
offset-path: view-box;

基本形状函数语法可以参见clip-path属性,这个在CSS领域中是通用的。

其中xywh()函数大家可能陌生,这是个矩形框函数,使用与包含块的左(x)和上(y)边的指定距离以及矩形的指定宽度(w)和高度(h)创建矩形。

rect()函数的区别在于,rect()函数通过距离矩形边缘的距离创建矩形。

至于ray()函数,表示射线,支持4个参数值。ray()函数最多接受四个参数:角度值、尺寸值(可选,支持closest-sideclosest-cornerfarthest-sidefarthest-cornersides)、可选关键字contain和可选位置。

此函数一般用来模拟射线射出的效果,日常使用机会不大,不做展开。

四、结束语

好,突发奇想,使用AI对本文总结下。

CSS offset-path 属性早在 8 年前就被介绍过,但当时仅支持不规则路径即 path () 函数。从 Safari 18 开始,该属性实现了在所有现代浏览器中的全面支持。其主要作用是实现各类炫酷的路径动画效果,如蚂蚁绕圈动画,借助 circle () 函数即可达成。offset-path 属性语法较为复杂,涵盖默认值 none 、线段(ray() 函数)、URL 路径、基本形状(circle() 、ellipse() 、inset() 等函数)以及坐标盒子。其中 xywh() 是创建矩形框的函数,与 rect() 函数创建矩形方式不同;ray() 函数表示射线,接受角度值、尺寸值、可选关键字 contain 和可选位置等参数,不过使用机会较少。

哟,还不错嘞,哈哈哈。

时间还早,写点碎碎念。

我的网站迁到海外服务器了,最近老折腾了。

为啥呢?当时为了这个备案,注册了个公司,想着,以后出来创业说不定需要。

后来么,疫情来了,被封了半年,心志也被磨了,也就没有创业的想法了。

然后这个公司就什么也不干,就这样挂着,结果每年好几大千的成本,最近实在受不了了,直接注销了,什么备案啊,账号啊,通通随他去了。

包括之前几个屯了快10年的域名(留着以后可能创业用的)也不续了。

我就每周写写东西,做做视频,钓钓鱼(抖音搜:最会钓鱼的程序员),不开心么,折腾个啥呢,还真能改变世界不成。

😋😛😝😜🤪

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11536

(本篇完)

HTML permission元素和Permissions API简介

2025-02-24 15:31:55

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11534
本文可全文转载,独立域名个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。

Permissions API占位图

本文介绍一个全新的HTML元素<permission>元素,与浏览器权限申请与使用相关,同时介绍Permissions API。

年纪上去了,精力有限,本文就不扯淡了,直接讲最核心的东西。

一、permission元素的作用

在Web开发的时候,我们会经常用到权限申请,比方说摄像头,访问相册,是否允许通知,又或者地理位置信息等。

权限提示

在过去,这种申请都是通过JavaScript代码触发的,使用各种权限专门的API,或者使用统一的Permissions API。

但是,JavaScript触发的这种权限选择会有个问题,那就是如果用户不小心点击了拒绝怎么办?

这个其实还挺常见,或者有时候用户正好和女朋友吵架,心情不好,这个时候出现个提示,想都不想就拒绝,也是很有可能的,对吧。

此时,想要恢复权限,就很麻烦,需要去浏览器设置里面去处理。

设置权限

这个对于那种非互联网重度用户而言,太难了。

于是,就有了<permission>元素。

权限按钮直接暴露在网页中,直接让用户点击就好了。

比方说下面的代码:

<permission type="camera" />

实时渲染效果如下(浏览器不支持会只有虚框):

在我windows chrome浏览器下的渲染效果则是:

使用摄像头示意

对应的HTML源码结构参见:

权限申请源码

此时,用户点击此按钮,就会自动呼起权限选择的框框,例如:

权限提示说明

此时,我们点击右上角的叉叉,不做任何选择,紧接着在点击此按钮,依然会出现提示。

这就避免了上面提到的用户权限选择拒绝后无法再次权限申请的问题。

眼见为实,您可以狠狠地点击这里:HTML permission元素不同类型展示效果demo

浏览器是否支持的检测

判断浏览器是否支持元素,可以使用下面展示的JS代码:

if ('HTMLPermissionElement' in window) {
  // The `<permission>` 元素支持
}

二、Permissions API又是什么

在不过去,不同类型的权限申请回使用各自专门的API去进行,比方说地址位置的申请使用navigator.geolocation,摄像头权限申请使用navigator.getUserMedia()等。

这就会导致开始使用的学习和使用成本比较高。

既然都是权限申请,且系统出现的提示UI都近似,何必来个大统一呢?在这种背景下,Permissions API被提出来了。

所有的权限申请全都使用一个统一的API名称入口,使用的方法是Permissions.query(),直接看案例,地址位置权限申请。

navigator.permissions.query({ name: "geolocation" }).then((result) => {
  if (result.state === "granted") {
    showLocalNewsWithGeolocation();
  } else if (result.state === "prompt") {
    showButtonToEnableLocalNews();
  }
  // 如果权限没通过就不执行任何操作
});

下面列表显示了各类权限API预支对应的权限名称:

  • Background Synchronization API: background-sync (这个结果应该都是granted)
  • Clipboard_API: clipboard-read, clipboard-write
  • Compute Pressure API: compute-pressure
  • Geolocation API: geolocation
  • Local Font Access API: local-fonts
  • Media Capture and Streams API: microphone, camera
  • Notifications API: notifications
  • Payment Handler API: payment-handler
  • Push API: push
  • Screen Wake Lock API: screen-wake-lock
  • Sensor APIs: accelerometer, gyroscope, magnetometer, ambient-light-sensor
  • Storage Access API: storage-access, top-level-storage-access
  • Storage API: persistent-storage
  • Web Bluetooth API: bluetooth
  • Web MIDI API: midi
  • Window Management API: window-management

不展开介绍。

三、两者结合使用?

既然都是与权限上面,那个HTML的这个和JS的这个是不是可以组合使用,没错,还真是,而且推荐这么处理。

下面是个案例,摄像头权限申请处理,看代码,先是HTML部分:

<permission type="camera" />

然后接下来看看实操的JS代码:

// 获取permission元素
const permission = document.querySelector('permission');
// 绑定事件
permission.addEventListener('promptdismiss', showCameraWarning);

function showCameraWarning() {
  // 显示摄像头会获取授权的提醒
}

// 使用Permissions API申请权限
const permissionStatus = await navigator.permissions.query({name: "camera"});
// 权限状态变化的处理
permissionStatus.addEventListener('change', () => {
  // 如果权限允许,使用相机该干嘛就干嘛
  if (permissionStatus.state === "granted") {
    useCamera();
  }
});

// 运行初始检查,如果用户之前已经通过,直接处理
if (permissionStatus.state === "granted") {
  useCamera();
}

大家平时开发的时候,就参照上面的案例处理就好了。

permission元素事件

上面代码出现的promptdismiss事件就是permission元素支持的事件类型之一。

具体有这么几个:

onpromptdismiss
用户关闭权限提示的时候触发。使用addEventListener绑定事件的时候,'on'需要省略,下同。在浏览器开启实验支持阶段,也可能使用的是ondismiss名称。
onpromptaction
当用户对元素触发的权限提示执行某些操作来解除该提示时,系统会触发此事件。这并不一定意味着权限状态已更改,用户可能已执行某项操作来维持现状(例如继续允许使用某项权限)。在非正式阶段,事件名称为onresolve
onvalidationstatuschange
当元素从valid状态切换成invalid时触发。默认情况下都是valid状态,但是,如果当前的permission元素被其他元素遮挡,则被视为invalid

PS:本来想测试下事件支持的名称,发现浏览器版本升级到最新之后,反而无法正常渲染permission元素了,怪哉,难道放弃支持了?

四、其他权限相关说明

目前Permissions API是可以放心使用的,浏览器支持有一段时日了,截图参考:

Permissions API兼容性

但是对于HTML <permission>元素,目前没有任何兼容性相关的数据,MDN上连个文档都没有,我怀疑,这个元素很有可能会中道崩殂。

另外 <permission>元素的样式是无法完全自定义的,毕竟与安全相关,仅有部分样式支持,综合上述,大家目前了解下即可。

好,就介绍这么多,希望可以对大家的工作与学习有所帮助。

也欢迎点赞,转发,一键……不好意思,说顺口,没有一键三连,转发就好了!

文章最后的小图-仙清儿

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=v

(本篇完)

不要搞混了,不是text而是CSS font-size-adjust属性

2025-02-12 21:01:24

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11527
本文可全文转载,独立域名个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。

font-size-adjust封面占位图

介绍一个前端新特性,CSS font-size-adjust属性,语法还有些小复杂,研究了下,怎么说呢,非常细节的一个CSS属性,设计的初衷是解决一个小众的问题场景。

一、不同字体下的字形大小问题

我们给一段文字设置同样大小的字号,要是字体的类型不同,那么呈现的大小就会有明显的不同。

例如,中文字体中的楷体就比雅黑和苹方字体显得小,英文字体中的Times字体就比Verdana字体显得小。

为了让整体字体下的视觉表现接近,于是就设计了font-size-adjust这个CSS属性,可以指定字体的尺寸。

参见下面的代码和截图示意:

<h4>中文字体</h4>
<p>我是中文内容,都是16px,最终的表现为?</p>
<p style="font-family: STKaiti, KaiTi">我是中文内容,都是16px,最终的表现为?</p>

明明都是16px,结果楷体的字形大小小了一圈:

楷体表现

英文也是类似的,衬线字体看起来都小了一圈。

<h4>英文字体</h4>
<p style="font-family: verdana">Welcome to support my new book - HTML is not simple</p>
<p style="font-family: Times">Welcome to support my new book - HTML is not simple</p>

英文衬线字体小一号

尤其英文,字体不同,其占据的宽度大小区别很大,这就导致,原本可以一行展示的内容,在其他设备上就是两行,而造成布局问题。

我们可以使用font-size-adjust进行微调,使细节完美。

使用Example案例

如何调整?可以根据小写字母x的高度占比进行统一设置。

以上面的案例继续举例,只需要增加这样一行代码,苹方和楷体的视觉大小就很很接近。

p {
  font-size-adjust: 0.545;
}

此时的中英文排版效果就会是这样:

font-size-adjust调整后的效果

为何这里的值是0.545呢?

因为Verdana字体的纵横比值的精确值就是0.545,当我们设置这个值的时候,无论什么字体的小写字母x都会按照0.545的纵横比渲染,于是Times这种字体的视觉表现,就会跟Verdana类似。

这就是font-size-adjust属性作用的原理,然而,font-size-adjust属性不仅仅这些,如果我们希望基于大写字母设置怎么办?如果希望基于字形的宽度设置,又如何?

这些font-size-adjust属性都支持,下面深入了解下font-size-adjust属性的语法。

二、深入font-size-adjust语法

先看一些语法使用示意:

/* 关键字值 */
font-size-adjust: none;

/* 单值:数值或者from-font */
font-size-adjust: 0.5;
font-size-adjust: from-font;

/* 两个值 */
font-size-adjust: ex-height 0.5;
font-size-adjust: ch-width from-font;

其中,from-font可以理解为是默认值,这个关键字的意思是,使用第一个识别的字体的某某特征,这不就是目前默认字体的渲染规则嘛。

故而,我们要需要重点关注的,就是数值类型,可以是直接一个数值,也可以是“字体度量”和数值的组合。

字体度量

字体度量总共支持5个类型,分别是:

ex-height
默认度量类型。也就是如果仅数值,则表示使用的是ex-heightex-height表示小写字母x的高度占比。
cap-height
使用大写字母高度与字体大小的比率来调整回退字体大小。此关键字值用于规范不同字体的大写字母。
ch-width
ch表示字母0 (ZERO, U+0030)的宽度,通过调整数字0占据宽度和font-size占比来调整文字的渲染尺寸。
ic-width
ic这个单位与中文“水”相关,ic-width就是“水”占据宽度和font-size占比。此度量类型虽说是为中文场景设计的,但是日常开发很少有机会使用,因为,根据我的观察,中文字体天然等宽,且常见的中文字体占据的高宽都是1em,很少遇到需要进行调整的机会。
ic-height
“水”占据高度和font-size占比。

经过我对这些字体度量类型的测试,得出了一个结论……嗯……还是只适用于英文场景,虽说提供了中文类型的支持,但是脱离实际,是个鸡肋作用。

例如上面的例子,虽说我们通过ex-height设置让楷体的字形大小和苹方(微软雅黑也是类似)接近,但是,文字所占据的宽度却明显加大的。

这个和英文不同,英文字体的字形宽高比往往是等比例变化的,也就是字形看起来小,宽度也会窄,此时我们使用ex-height调整就会和合适,不仅字形看起来一样大,占据的宽度也类似。

三、是否影响em等相对单位

font-size-adjust属性可以让文字放大或者缩小,那么会不会影响em这些相对单位的计算呢?我觉得是不影响的。来看一个例子:

<p><img src="icon_del.png">删除</p>
p {
  font-size-adjust: ic-width 2;
}
p img {
  width: 1em;
  height: 1em;
}

设置图标尺寸和字体大小一模一样,结果其渲染结果是下面这样,字形很大,但图标却小,就是因为字形是200% font-size大小,图标是100%,说明font-size-adjust属性并不会影响em属性的作用。

删除图标

四、一些可能的应用场景思考

CSS这门语言很神奇,有时候,某些CSS属性大放异彩,往往不是因为其原本设计的初衷,比方说float属性。

我觉得font-size-adjust属性的妙用可能还在于,不改变font-size尺寸的前提下,改变文字的尺寸。

又或者说,实现12px字号以下的中文字体。

在过去,Chrome对此有限制,现在,获取就很easy了。

例如:

欢迎关注我的抖音账号“张鑫旭本人”,
<span style="font-family: sans-serif; font-size-adjust: ic-width 0.625">
  字号大小只有10px
</span>

实时渲染效果如下所示(浏览器版本不够会看不到效果):

欢迎关注我的抖音账号“张鑫旭本人”,字号大小只有10px

我发现字体设置为 system-ui 只有英文数字会10px,中文字体并不会,好生奇怪。

五、和text-size-adjust和size-adjust关系

font-size-adjust还有两个近似CSS属性,分别是text-size-adjustsize-adjust

text-size-adjust一般用在移动端,使用方法通常是设置none,例如:

body {
  -webkit-text-size-adjust: none;
  text-size-adjust: none;
}

是这样的,在移动端,对于Web网页,你如果将手机横屏流量,由于设备的宽度增加了,为了更好的阅读体验,浏览器会自动调整页面的字号,回放大。

但往往在实际开发的时候,是不需要这种自动字号调整的,因此,需要设置text-size-adjust:none

size-adjust属性呢?

size-adjust我之前有介绍过,看了下。22年的文章,“使用CSS size-adjust和unicode-range改变任意文字尺寸”。

这个CSS属性也是改变文字现实尺寸的,只不过需要和自定义字体一起使用,需要设置在@font-face规则中。

我觉得,现在有了font-size-adjust属性,size-adjust属性被使用的概率会大大下降,因为前者更加灵活,使用成本更低。

除非什么呢?除非你只需要某些文字字号不一样,比方说一段文本,所有中文都是大号文字,字母数字都是正常,那就使用size-adjust,因为可以配合unicode-range指定字号调整的字符集范围。

总之,如今的CSS,对于文本尺寸的控制能力是越来越强了。

六、兼容性、结语说明

font-size-adjust还是个比较新的CSS属性,不过目前所有现代浏览器都支持了,如下图所示:

font-size-adjust兼容性图

我看了下日期,Chrome是2024年7月才支持的,到现在也就半年时间。

大规模应用还需数年时间,在这段时间,可以先使用size-adjust属性聊以慰藉。

OK,就说这些,感谢大家的阅读,又什么想法欢迎评论交流。

我们下周再见~

👋🏻👋🏻👋🏻👋🏻

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11527

(本篇完)

JS Set新支持了intersection, union, difference等方法

2025-02-10 21:46:12

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11522
本文可全文转载,独立域名个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。

JS SET API占位图

继续介绍前端前沿新特性,今天讲的是Set或者类似Set的数据新支持的若干方法,主要是交集、合集以及差异判定相关,API较多,一个一个来。

一、intersection交集

单词’intersection’就是交叉,交集的意思。

用数学公式表示就是:

AB={xAxB}A\cap B = \{x\in A\mid x\in B\}

用更直观的图形表示则为:

交集图形示意

应用举例

已知数组A和数组B,请返回两个数组相同的数组项。

在过去,是需要对两个数组分别循环处理,现在就是一行代码的事情,参考实现:

const arr1 = ['CSS世界', 'CSS新世界', 'HTML并不简单'];
const arr2 = ['CSS选择器世界', 'CSS新世界'];
// 相同数组项
console.log([...new Set(arr1).intersection(new Set(arr2))]);
// 返回结果是:
// ['CSS新世界']

例如,在Chrome console控制台的运行结果截图:

数组合并运行结果示意

二、union合集

union()方法可以让Set或者类Set对象的值进行合并(同时去重)处理。

语法示意:

set1.union(set2)

数学公式表示:

AB={xxA or xB}A\cup B = \{x\midx\in A\text{ or }x\in B\}

图形表示:

合集效果图形示意

案例示意

const arr1 = ['CSS世界', 'CSS新世界', 'HTML并不简单'];
const arr2 = ['CSS选择器世界', 'CSS新世界'];
// 合并去重
console.log([...new Set(arr1).union(new Set(arr2))]);
// 返回结果是:
// ['CSS世界', 'CSS新世界', 'HTML并不简单', 'CSS选择器世界']

下图所示的就是运行结果:

数组合并去重

三、difference和symmetricDifference差集

Set.prototype.difference()返回的是另外一个Set对象和自身不同的部分。

用MathML数学表达式示意:

AB={xAxB}A\setminus B = \{x\in A\mid x\notin B\}

还是下面的圆形图像更直观:

Set差集示意

Example – 案例

const arr1 = ['CSS世界', 'CSS新世界', 'HTML并不简单'];
const arr2 = ['CSS选择器世界', 'CSS新世界'];
// 返回不一样的部分
console.log([...new Set(arr1).difference(new Set(arr2))]);
// 返回结果是:
// ['CSS世界', 'HTML并不简单']

随意打开一个页面的console输入框,粘贴回车测试下,果然是这个输出内容:

difference案例运行结果

注意,返回的是调用对象的差值,而不是所有对象不同的部分。

如果想要取所有对象的差值部分,请使用symmetricDifference()方法。

symmetricDifference对称差集

公式和图示:

AB=(AB)(BA)A\ominus B = (A\setminus B)\cup(B\setminus A)

对称差集示意

例如:

const arr1 = ['CSS世界', 'CSS新世界', 'HTML并不简单'];
const arr2 = ['CSS选择器世界', 'CSS新世界'];
// 返回不一样的部分
console.log([...new Set(arr1).symmetricDifference(new Set(arr2))]);
// 返回结果是:
// ['CSS世界', 'HTML并不简单', 'CSS选择器世界']

四、isDisjointFrom()是否无重合

Set对象还支持了三个逻辑判断的方法。

首先是isDisjointFrom()方法,用来判断Set集是不是没有任何重合,也就是是不是没有交集,单词disjoint的意思就是“不相交;相离;”。

用数学符号表示:

A is disjoint from BAB=A\text{ is disjoint from }B \Leftrightarrow A\cap B = \empty

使用维恩图表示:

不相交示意

举个例子

下面arr1和arr2都有相同的数组项'CSS新世界',因此,最后输出的值就是false,是有相同的值,彼此是有相交的。

const arr1 = ['CSS世界', 'CSS新世界', 'HTML并不简单'];
const arr2 = ['CSS选择器世界', 'CSS新世界'];
// 是否彼此独立
console.log(new Set(arr1).isDisjointFrom(new Set(arr2)));
// 返回结果是:false

但如果将数组arr1里面的数组项'CSS新世界'去掉,那么返回的就会使true,两个数组没有任何项目是重复的。

const arr1 = ['CSS世界', 'HTML并不简单'];
const arr2 = ['CSS选择器世界', 'CSS新世界'];
// 是否彼此独立
console.log(new Set(arr1).isDisjointFrom(new Set(arr2)));
// 返回结果是:true

五、isSubsetOf()是否被包含

语法:

setA.isSubsetOf(setB)

表示setA是否被setB包含。

用专门的数学符号公式表示:

ABxA,xBA\subseteq B \Leftrightarrow \forall x\in A,\,x\in B

用逻辑关系图表示:

被包含关系示意

案例演示

包含于被包含还是很好理解的,就是是不是所有A的值都在B里面。

下面是MDN上的例子,请看:

const fours = new Set([4, 8, 12, 16]);
const evens = new Set([2, 4, 6, 8, 10, 12, 14, 16, 18]);
console.log(fours.isSubsetOf(evens)); // true
const primes = new Set([2, 3, 5, 7, 11, 13, 17, 19]);
const odds = new Set([3, 5, 7, 9, 11, 13, 15, 17, 19]);
console.log(primes.isSubsetOf(odds)); // false

如果两个数组是一样的,那么如果谁包含谁,都可以认为是true,比方说:

const set1 = new Set([1, 2, 3]);
const set2 = new Set([1, 2, 3]);
console.log(set1.isSubsetOf(set2)); // true
console.log(set2.isSubsetOf(set1)); // true

六、isSupersetOf()是否包含

isSupersetOf()表示调用的Set对象是否包含被调用的Set对象。

数学符号表示其逻辑关系:

ABxB,xAA\supseteq B \Leftrightarrow \forall x\in B,\,x\in A

或是使用Venn图表示:

包含关系示意

至于案例,和isSubsetOf()方法类似,这里就不重复展示了。

七、兼容性、polyfill等

本文所介绍的6个Set方法,其兼容性都是一样的,浏览器同时支持的,还算比较新的方法。

Set新方法兼容性

由于这几个方法,浏览器支持的时间还不算很长,因此,如果要在生产环境使用,建议引入Polyfill或者shim。

Polyfill地址:https://github.com/zloirock/core-js#new-set-methods
Shim地址:https://github.com/rauschma/set-methods-polyfill

其他

同事陆续归为,从今天开始,正式进入工作状态。

2025年啊,三件事情,写小说,持续前端专业输出,以及钓鱼记录。

持之以恒,静待开花结果。

感谢阅读,欢迎

哪吒图

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11522

(本篇完)

JS Array数组新的with方法,你知道作用吗?

2025-02-06 21:42:25

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11519
本文可全文转载,独立域名个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。

数组Array with占位图

一、不改变原数组进行设置

先看使用场景。

在过去,我们修改某个数组项,通常会使用索引值进行设置,例如将数组的第2项修改为某某电影名称:

const arr = ['魔童闹海', '蛟龙行动', '侠之大者', '唐探1900'];
// 修改数组第2项
arr[1] = '流浪地球';

但这种修改会改变原数组。

如果我们希望原数组不发生改变,在过去,都是先要复制一下数组,然后再处理。

复制数组的方法非常多,下面这些方法都可以:

// 原数组
const fruits = ["Apple", "Mango"];

// 复制数组,使用...扩展语法
const fruitsCopy = [... fruits]

// 复制数组,使用from()静态方法
const fruitsCopy2 = Array.form(fruits)

// 复制数组,使用slice()方法
const fruitsCopy3 = fruits.slice()

// 复制数组,使用concat()方法
const fruitsCopy4 = fruits.concat()

我个人比较喜欢使用slice()方法,语义好的同时兼容性也好,使用示意:

const arr = ['魔童闹海', '蛟龙行动', '侠之大者', '唐探1900'];
// 修改数组第2项
const arr2 = arr.slice();
arr2[1] = '流浪地球';

现在可以使用with()方法

而如今,无需像过去这般麻烦,复制数组同时设置数组项的值有了专门的API方法,为Array.prototype.with()方法,使用示意:

const arr = [, '唐探1900', '侠之大者', '蛟龙行动'];
// 结果是 ['哪吒魔童闹海', '唐探1900', '侠之大者', '蛟龙行动']
console.log(arr.with(0, '哪吒魔童闹海'));

在Chrome控制台中的运行结果示意:

with运行结果截图示意

二、with的语法和兼容性

下面简单介绍下with()方法的语法。

语法

arrayInstance.with(index, value)

其中:

  • index是索引值,可以是负数(最终的索引值=负数+数组长度),该参数的含义和数组的at()方法一样。如果索引值超出范围,则会报错,这个要注意下。
  • value没什么好说的,就是修改的值。如果该参数不设置,则对应的数组项会变成 undefined

基本上,在目前的Web开发建议中,数组读取使用at()方法,写值使用with(),相得益彰。

兼容性

2023年左右支持的,目前所有现代浏览器都支持,具体参见下面的caniuse截图:

with方法兼容性

不过在正式对外的项目中最好引入Polyfill代码,避免异常。

类似的Polyfill项目很多,这里是我找的实现源码参考

polyfill源码参考

三、其他保留原数组的方法

with()一同支持的还有不少其他方法,都可以保留原数组的同时实现数组的相关处理,包括反序,排序和切割等。

包括:

  • toReversed(),不改变原数组,同时数组反序,返回值是新数组。改变原数组的反序方法是reverse()方法,参数都是一样的。
  • toSorted(),不改变原始数组,同时对数组进行排序,返回内容是新数组。对应的原始方法是sort()方法,两者参数一致。
  • toSpliced(),不改变原来的数组,同时可以对数组进行切割和插入操作,返回处理后的新数组。老方法是splice()方法,参数雷同。

在React和Vue开发的时候,有时候需要对数组进行处理的时候,不改变原数组(不会自动触发重绘),上面这些方法都是可以考虑的。

浏览器同一时期支持的,因此,兼容性是一样的。

四、新年伊始,开工大吉

好吧,本文就这么点内容。

春节结束,开工大吉,新的一年算是开始了。

继续保持对前端的好奇心,不断学习,静待开花结果。

新年开工大吉

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11519

(本篇完)