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

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 三生石上(FineUI控件)
美团技术团队
Last Week in AI
Last Week in AI
WordPress大学
WordPress大学
L
LangChain Blog
雷峰网
雷峰网
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 叶小钗
Engineering at Meta
Engineering at Meta
腾讯CDC
Recent Announcements
Recent Announcements
The Register - Security
The Register - Security
有赞技术团队
有赞技术团队
Blog — PlanetScale
Blog — PlanetScale
博客园 - Franky
博客园 - 司徒正美
The Cloudflare Blog
Google DeepMind News
Google DeepMind News
T
Tailwind CSS Blog
C
Check Point Blog
小众软件
小众软件
V
Visual Studio Blog
V
V2EX
F
Full Disclosure
J
Java Code Geeks
MongoDB | Blog
MongoDB | Blog
罗磊的独立博客
人人都是产品经理
人人都是产品经理
量子位
Apple Machine Learning Research
Apple Machine Learning Research
F
Fortinet All Blogs
Microsoft Security Blog
Microsoft Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 【当耐特】
博客园_首页
Y
Y Combinator Blog
N
Netflix TechBlog - Medium
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
Recorded Future
Recorded Future
G
Google Developers Blog
Vercel News
Vercel News
大猫的无限游戏
大猫的无限游戏
Microsoft Azure Blog
Microsoft Azure Blog
U
Unit 42
爱范儿
爱范儿
Jina AI
Jina AI

张鑫旭-鑫空间-鑫生活

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数组的copyWithin()语法我看了好几遍才懂 « 张鑫旭-鑫空间-鑫生活
张鑫旭,zhangxinxu · 2022-12-28 · via 张鑫旭-鑫空间-鑫生活

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

copywithin封面图

一、copyWithin()对比slice()

JavaScript中数组的copyWithin()和slice()方法作用都是复制数组,且都是浅复制。

区别之一在于

copyWithin()是将数组中的一部分复制并替换另外一部分,总长度是不变的,而slice()方法只复制,不替换,返回的数组长度是由复制的数组项目个数决定的。

看一个区别,已知数组 arr[1, 'A', '甲', 'I'],则分别执行 arr.copyWithin(2, 3)arr.slice(2, 3) 会有如下所示的不同结果。

arr = [1, 'A', '甲', 'I'];
console.log(arr.copyWithin(2, 3));
// 结果是: [1, 'A', 'I', 'I']
arr = [1, 'A', '甲', 'I'];
console.log(arr.slice(2, 3));
// 结果是: ['甲']

在控制台运行结果如下图所示:

两个数组复制方法运行结果对比

区别之二在于

copyWithin()方法会改变原始的数组,而slice()方法并不会。

例如:

arr = [1, 'A', '甲', 'I'];
arr.copyWithin(2, 3);
console.log(arr);
// 结果是: [1, 'A', 'I', 'I']
arr = [1, 'A', '甲', 'I'];
arr.slice(2, 3);
console.log(arr);
// 结果是:[1, 'A', '甲', 'I']

控制台运行结果如下图所示:

影响原数组示意

可以看到,copyWithin()方法执行后,原始的arr数组发生了变化,变成了复制后的数组内容。

区别之三在于

slice()复制对于字符串也是有效的,但是copyWithin()方法却不支持。

例如:

// 返回值是'angx'
('zhangxinxu').slice(2, 6)

但是下面的语句就会报错:

// 会无情报错
('zhangxinxu').copyWithin(2, 6)

二、copyWithin()的语法

copyWithin()的语法形式上不算复杂,但是理解起来有些费脑细胞,我也是看了好几遍才弄明白。

语法

Array.prototype.copyWithin(index, start, end)

表示复制start-end的内容,并从index开始替换。

使用示意:

[].copyWithin()
[].copyWithin(index)
[].copyWithin(index, start)
[].copyWithin(index, start, end)

参数

index
复制的数组项开始替换的起始索引值。
start
复制的数组项的起始位置(包含)。
end
复制的数组项的结束位置(不包含)。

举例说明

例如:

arr = [1, 'A', '甲', 'I', '一'];
arr.copyWithin(2, 3, 4);

此时,start=3,end=4,表示复制数组的arr[3](包含)到arr[4]项(不包含),因此复制的值是 arr[3],也就是 ‘I’。
index=2,则表示复制的值从arr[2]这里开始替换。

copyWithin原理示意

于是复制的结果就是:[1, ‘A’, ‘I’, ‘I’, ‘一’]

参数细节

copyWithin()方法的参数细节比较多,毕竟数值有大有小,有正有负,情况不同,规则也会不同。

具体如下:

1. index参数

  • index参数不设置也是合法的,不过你不设置该参数数组就会原路复制返回,类似于设置为 0,这样处理只会浪费性能,没有任何实际意义。

    因此,index参数可以认为是必须参数。

  • 如果index是小数,则会按照整数处理,并且是向下取整。例如:
    // 返回值是 true
    [1, 2, 3].copyWithin(1.5).join() == [1, 2, 3].copyWithin(1).join()
    // copyWithin(1.5)执行结果是:[1, 1, 2]
  • 如果index是负数。
    • 如果index负数的绝对值很大,甚至比数组的长度还要大,则此时 index 当作 0 处理。例如:
      // 返回值是 ['zhang', 'xin', 'xu']
      // 等同于 copyWithin(0)
      ['zhang', 'xin', 'xu'].copyWithin(-999)
    • 否则,最终的 index 值等于 index + arr.length,比方说 [1, 2, 3].copyWithin(-1) 就等同于 [1, 2, 3].copyWithin(2)
      // 结果是[1, 2, 1]
      [1, 2, 3].copyWithin(-1);
      // 结果同样是[1, 2, 1]
      [1, 2, 3].copyWithin(2);

      负数 index 值效果示意

  • 如果index的值超出了数组的长度范围,则不会有任何内容被复制。这里需要注意下,没有任何内容复制和所有内容都复制是有区别的,虽然看起来返回的都像是原数组,但其实并不是,性能这块是有着明显的差异的。

    我们可以用非常简单的方法测试下,例如我们构造一个99万个项目的数组进行复制处理:

    console.time('start');
    arr = new Array(999999);
    console.timeLog('start');
    arr.copyWithin(0);
    console.timeLog('start');
    arr.copyWithin(1000000);
    console.timeEnd('start');

    我们在控制台跑一下上面的代码,通过观察执行时间就会发现执行copyWithin(0)用了近70ms,而执行copyWithin(1000000)的用时几乎就是0.

    运行时间对比

  • 如果 index 的位置在 start 之后,则复制的内容粘贴到数组长度的尾部就停止了,也就是不会增加数组的长度的:

    例如:

    // 结果是 [1, 'A', '甲', 'A', '甲']
    [1, 'A', '甲', 'I', '一'].copyWithin(3, 1);

2. start参数

  • start参数是可选的,如果不设置,则当作0处理,表示数组从头复制到尾部(index小于数值长度的前提下);
  • start如果是小数,会向下取整处理。例如[].copyWithin(0, 1.9999)等同于 [].copyWithin(0, 1)
  • start如果是负数,则从数组的后面开始取值,等同于 start + arr.length;
  • start如果是负数,同时绝对值小于 -1 * arr.length,则当作 0 处理。
  • start如果超出数组的长度范围,则不会发生复制。

2. end参数

  • end参数是可选的,如果不设置,则当作array.length处理,表示数组复制到尾部;
  • end如果是小数,会向下取整处理。例如[].copyWithin(0, 1, 2.999)等同于 [].copyWithin(0, 1, 2),例如:
    // 结果是:[2, 2, 3, 4]
    [1, 2, 3, 4].copyWithin(0, 1, 2.9999)
  • end如果是负数,则从数组的后面开始取值,等同于 end + arr.length;
  • end如果是负数,同时绝对值小于 -1 * arr.length,则当作 0 处理。
  • end如果超出数组的长度范围,则当作array.length处理。
  • 如果end对应的位置比start小,则不会发生复制。

三、copyWithin实际应用

我想的一些应用,也找了一些应用, 欢迎大家补充更适合使用copyWithin()的场景。

1. 删除数组中间某一项

数组删除第一个项目可以使用 shift() 方法,删除最后一个项目可以使用 pop() 方法,但似乎没有删除中间某一项的方法。

在过去都是使用 splice() 方法实现的,语法示意:

[].splice(index, 1);

现在多了个选择,使用 copyWithin(),例如:

[].copyWithin(index, index + 1).pop();

例如,删除数组 arr 中的 第 2 项:

arr = ['甲', '乙', '丙', '丁'];
arr.copyWithin(1, 2).pop();
// 结果是['甲', '丙', '丁']
console.log(arr);

2. 置顶数组某一项

这种数组总长度不变的场景比较适合 copyWithin 方法:

// 自定义top置顶方法
Array.prototype.top = function (index) {
    const value = this[index];
    this.copyWithin(1, 0, index);
    this[0] = value;
};

例如:

arr = ['甲', '乙', '丙', '丁'];
arr.top(1);
// 结果是["乙", "甲", "丙", "丁"]
console.log(arr);

3. 模拟插入排序算法

下面这个案例源自这个stackoverflow

const insertionSort = (data, compare) => {
  const arr = [...data];
  let unsort_index = 1;

  while (unsort_index < arr.length) {

    while (arr[unsort_index] >= arr[unsort_index - 1]) unsort_index += 1;
    const pick = arr[unsort_index];

    let iter = 0;
    while (iter < unsort_index && arr[iter] < pick) iter += 1;
    arr.copyWithin(iter + 1, iter, unsort_index);
    arr[iter] = pick;

    unsort_index += 1;
  }
  return arr;
}

const input = [2, 3, 5, 1, 9, 8, 6, 6];
const asc = (a, b) => a - b;
const dsc = (a, b) => b - a;

console.log({ input, asc_sorted: insertionSort(input, asc) });
console.log({ input, dsc_sorted: insertionSort(input, dsc) });

等。

四、结束语

copyWithin()是一个非常高性能的数组移动方法。

不过,我查找了一圈,暂时没有发现特别适合这个方法的应用场景,理论上,这个仅适合当前数据内复制并粘贴的场景。

比方说一张画布内复制粘贴,对于在数据层面,这样的场景并不多,因为直接覆盖数据,还是用旁边的数据覆盖,并不常见。

也可能是自己目前所接触的开发场景还不够多。

希望以后可以碰到特别适合使用 copyWithin() 方法使用的场景。

好了,以上就是本文的全部内容了。

如果你觉得写得还不错,欢迎转发!

?

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

(本篇完)