CSS
pageY、clientY与screenY的差别(X同理)
html5
中a
的download
属性
定义和用法
`download` 属性定义**下载链接的地址**或**指定下载文件的名称**。文件名称没有限定值,浏览器会自动在文件名称末尾添加该下载文件的后缀 `(.img, .pdf, .txt, .html, 等)`。
download
属性是HTML5
中新增的<a>
标签属性。
语法 | 属性值 | 值 描述 |
---|---|---|
<a download="filename"> | filename | 指定文件名称。 |
检测浏览器是否支持download
属性
'download' in document.createElement('a');
1px
边框(解决不同分辨率屏幕1px的宽窄不同)
缩放原理
.border-1px {
position relative
}
.border-1px:after {
display block
content ''
position absolute
left 0
bottom 0
width 100%
border-top 1px solid #ccc
}
@media (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5) .border-1px::after {
transform scaleY(0.7)
-webkit-transform scaleY(0.7)
}
@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2)
.border-1px::after {
transform scaleY(0.5)
-webkit-transform scaleY(0.5)
}
@media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3)
.border-1px::after {
transform scaleY(0.3333)
-webkit-transform scaleY(0.3333)
}
隐藏移动端ios/android
滚动条,使滚动流畅
隐藏滚动条,不影响滚动
::-webkit-scrollbar
display none
流畅滚动
//在滚动元素`css`中添加
-webkit-overflow-scrolling touch // IOS系统
overflow-scrolling touch // 安卓系统
伪元素(:或::都可以,::更准确,:兼容好)
与伪类(只能:)
的区别
伪类与伪元素都是用于向选择器加特殊效果
- 伪类与伪元素的本质区别就是
是否抽象创造了新元素
- 伪类只要不是互斥可以叠加使用
- 伪元素在一个选择器中只能出现一次,并且只能出现在末尾
- 伪类与伪元素优先级分别与类、标签优先级相同
伪类标签只对可以插入内容的标签添加:div
span
:focus-within
表示一个元素获得焦点,或,该元素的后代元素获得焦点
使用示例(掘金的登录框):
代码CSS:
* {
margin: 0;
padding: 0;
}
.wrap {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.3);
}
.container {
font-size: 12px;
position: relative;
padding: 2rem;
width: 26.5rem;
max-width: 80%;
box-sizing: border-box;
background-color: #fff;
border-radius: 6px;
}
h2 {
margin: 0 0 2rem;
}
.panfish img {
width: 8rem;
position: absolute;
left: 50%;
top: -48%;
transform: translate(-50%, 0);
}
.panfish .greeting {
top: -42%;
}
.panfish .normal {
top: -38%;
}
.panfish .blindfold {
top: -36%;
}
.input-box {
/* position: relative; */
margin-bottom: 0.8rem;
}
.form-input {
padding: 10px;
width: 100%;
border: 1px solid #e9e9e9;
border-radius: 2px;
outline: none;
box-sizing: border-box;
}
.greeting, .blindfold {
display: none;
}
.input-box:focus-within input {
border-color: #007fff;
}
.container:focus-within .normal {
display: none;
}
.username:focus-within .greeting {
display: block;
}
.pwd:focus-within .blindfold {
display: block;
}
HTML:
<div class="wrap">
<div class="container">
<h2>登录</h2>
<div class="panfish">
<img src="https://b-gold-cdn.xitu.io/v3/static/img/normal.0447fe9.png" class="normal" />
</div>
<div class="input-box username">
<input class="form-input" type="text" placeholder="请输入手机号或邮箱" />
<div class="panfish">
<img src="https://b-gold-cdn.xitu.io/v3/static/img/greeting.1415c1c.png" class="greeting" />
</div>
</div>
<div class="input-box pwd">
<input class="form-input" type="password" placeholder="请输入密码" />
<div class="panfish">
<img src="https://b-gold-cdn.xitu.io/v3/static/img/blindfold.58ce423.png" class="blindfold" />
</div>
</div>
</div>
</div>
::selection
被用户选中或处于高亮状态的部分
p::selection { color: white; background-color: red; } //选中p标签文字时的样式是红底白字
只可以应用于少数的CSS属性:color, background, cursor,和outline
::-webkit-scrollbar
滚动条样式
div::-webkit-scrollbar { /* 滚动条样式width等 */ }
::-webkit-scrollbar-track
滚动条元素 即整个滚动条轨道
::-webkit-scrollbar-thumb
滚动条滑块样式
Vue
中使用less
根据分辨率给元素添加背景图片
按照less
官方文档,url
应当如下使用:
URLs
// Variables
@images: "../img";
// Usage
body {
color: #444;
background: url("@{images}/white-sand.png");
}
故而有了根据屏幕分辨率设置背景图片代码
.bg-image(@url) {
background-image: url('@{url}@2x.png');
@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3){
background-image: url('@{url}@3x.png');
}
} // 报错报错 找不到路径的
这里要使用“~”
符号来告诉less
引号里面的内容不需要编译。
正确代码:
.bg-image(@url) {
background-image:~"url('@{url}@2x.png')";
@media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3) {
background-image: ~"url('@{url}@3x.png')";
}
}
改变输入框input
,textarea
的placeholder
样式,去除输入框选中边框高亮
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
//设置样式
}
input:focus { outline:none;} /* focus 标记*/
(原谅我一直没找很完善的reset.css,这些在一些重置样式文件自带的有,大家有好的完善的也可以告知我一下 )
user-select
控制用户选中文本
user-select: [prop]
prop | result |
---|---|
none | 元素及其子元素的文本不可选中 |
text | 用户可以选择文本 |
auto | 在 ::before 和 ::after 伪元素上,计算属性是 none , 详情 |
移动端慎用user-select:none
,会导致输入框等表单框失效
sticky
属性
在使用 position: sticky
的时候,如果不指定 top
属性是不会有效果的。
这个属性是用来实现滚动吸顶的,具体可了解position。
列表自动计数器
couter-reset
创建/重置一个或多个计数器counter-increment
递增一个或多个计数器值 通常作用于counter-reset
和content
属性
示例:
ul {
counter-reset: counter; /*这个counter只是个名字 和下边counter-increment和content对应*/
}
li::before {
counter-increment: counter;
content: counters(counter, '.') ' ';
}
列表渲染效果: 1. --- 2. -----
flex
布局属性中inline-flex
inline-flex
和 inline-block
一样,对内部元素
来说是个 display:flex
的容器,对外部元素
来说是个 inline-block
的块
textarea的换行符显示
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-all;
JS
fetch 请求的抛弃 以及抛弃请求的捕捉
let controller = new AbortController();
let signal = controller.signal;
fetch(url, { ... , signal }).then(res => { res.json() }).then(...)
//抛弃请求 会抛出一个DOMException
controller.abort();
关于抛出的DOMException
捕捉
err.name !== 'AbortError' && this.request_error('网络异常');
滚动条的控制
JS控制滚动条的位置:
ele.scrollTo(x,y);
//滚动到指定位置ele.scrollBy(x,y);
//滚动指定距离ele.scrollTop = y
//滚动指定位置 纵向ele.scrollLeft = x
//滚动指定位置 横向JS控制TextArea滚动条自动滚动到最下部
scrollHeightdocument.getElementByIdx\_x('textarea').scrollTop = document.getElementByIdx\_x('textarea').scrollHeight
- 获得滚动条距离顶部位置 ele.scrollTop 左边位置 ele.scrollLeft
function getScrollTop(){
var scrollTop=0;
if(document.documentElement&&document.documentElement.scrollTop){
scrollTop=document.documentElement.scrollTop;
}else if(document.body){
scrollTop=document.body.scrollTop;
}
return scrollTop;
}
addEventListener
VS
onclick
孰优孰劣
两个都可以实现效果。addEventListener
以及 IE
的 attachEvent
可以实现绑定多个事件,如果你有这方面的需求的话(奇怪的是你总会的)。addEventListener
的第三个参数可以用来控制监听器对于冒泡事件的响应,大部分情况是false,如果置为true,则响应事件的捕获阶段。事件的响应分区为三个阶段 :捕获、目标、冒泡阶段。onclick
绑定的多个事件会被覆盖,后者覆盖前者。
考虑到兼容ie,可以写一个原生的事件绑定兼容方案:
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
// example
addEvent(
document.getElementById('myElement'),
'click',
function () { alert('hi!'); }
);
参考链接:addEventListener 与 onclick
原生实现getScript
/**
* 动态添加JavaScript
* @param {*} url 资源地址
* @param {*} callback 回调方法
*/
function getScript(url, callback) {
var script = document.createElement('script');// 创建script元素
script.type = "text/javascript"; // 定义script元素的类型(可省略)
if (typeof (callback) != "undefined") { // 判断是否使用回调方法(第二个参数)
if (script.readyState) {// js状态
console.log(script.onreadystatechange); // onreadystatechange:js状态改变时执行下方函数
script.onreadystatechange = function () {
if (script.readyState == "loaded" || script.readyState == "complete") { // loaded:是否下载完成 complete:js执行完毕
script.onreadystatechange = null;
callback();
}
}
} else {
script.onload = function () {
callback();
}
}
}
script.src = url; // js地址
document.body.appendChild(script);// 插入body可改为head
}
addEventListener
第三个参数的passive
属性
最开始,addEventListener()
的参数约定是这样的:
el.addEventListener(type, listener, useCapture)
el
:事件对象type
:事件类型,click
、mouseover
等listener
:事件处理函数,也就是事件触发后的回调useCapture
:布尔值,是否是捕获型,默认false
(冒泡)
2015年底,为了扩展新的选项,DOM 规范做了修订:
el.addEventListener(type, listener, {
capture: false, // useCapture
once: false, // 是否设置单次监听
passive: false // 是否让阻止默认行为preventDefault()失效
})
复制代码三个属性的默认值都为 false
。如果事件是 touchstart
或 touchmove
的话,passive
的默认值则会变成true
图片上传按钮以及预览(转载+解析)
//代码来源:https://www.jb51.net/article/120617.htm 这里解析一下
<template>
<div class="admin">
<div class="admin-content">
<div class="edit">
<div class="avatar">
<div class="img">
<img :src="avatar" @click="setAvatar">
<span>更改</span>
</div>
//图片上传按钮
<input type="file" name="avatar" accept="image/gif,image/jpeg,image/jpg,image/png" style="display:none" @change="changeImage($event)" ref="avatarInput">
</div>
<button type="button" @click="edit">确认修改</button>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
avatar: this.$store.state.administrator.avatar,
}
},
methods: {
edit() {
// 确定修改后上传
if (this.$refs.avatarInput.files.length !== 0) {
var image = new FormData()
image.append('avatar', this.$refs.avatarInput.files[0])
this.axios.post('/avatar', image, {
headers: {
"Content-Type": "multipart/form-data"
}
})
}
},
setAvatar() {
//触发按钮的上传事件 也会用label绑定for属性
this.$refs.avatarInput.click()
},
changeImage(e) {
//从事件对象里获取文件,利用文件流读取
var file = e.target.files[0]
var reader = new FileReader()
var that = this
reader.readAsDataURL(file)
reader.onload = function(e) {
that.avatar = this.result
}
}
}
}
</script>
对象数组排序
主要用到Array
的sort()
方法:
语法
arr.sort([compareFunction])
参数
`compareFunction` 可选 用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的`Unicode`位点进行排序。
返回值
**排序后的数组**。请注意,数组已原地排序,并且不进行复制,即**数组已修改**。
如果没有指明 compareFunction ,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。例如 "Banana" 会被排列到 "cherry" 之前。当数字按由小到大排序时,9 出现在 80 之前,但因为(没有指明 compareFunction),比较的数字会先被转换为字符串,所以在Unicode顺序上 "80" 要比 "9" 要靠前。
如果指明了 compareFunction
,那么数组会按照调用该函数的返回值排序。即 a
和 b
是两个将要被比较的元素:
- 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
- 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);
- 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。
通俗点讲,那数字排序为例,return a - b
: 从小到大;return b - a
: 从大到小。
常用的是对象数组的排序,根据对象某一键值对排序,如下:var compare = function (prop) { return function (obj1, obj2) { var val1 = obj1[prop]; var val2 = obj2[prop]; /* *异常处理,或者转型处理字符串转数字比较等 */ if (val1 < val2) { return -1; } else if (val1 > val2) { return 1; } else { return 0; } } }
一键复制功能
主要用到 document.execCommand
copy() {
let googleSecuritKey = document.getElementById('googleSecuritKey');
googleSecuritKey.select();
try{
if(document.execCommand('copy', false, null)){
document.execCommand('copy');
//一个弹窗组件而已
this.$alert({
msg: '已复制至剪贴板!'
}, true);
}
} catch (err){
this.$alert({
msg: '请选中后按command/ctrl+C或右键复制!'
}, true);
}
},
该方法限制条件
:
- DOM元素要可编辑,比如
input
或者eidtable
属性的div
; - 不可有
disabled
属性,input
的type
不可以是hidden
; 内容宽度
不可为0,至少为1px;
那么如果做一个只做信息展示的内容,允许用户一键复制,怎么做呢?
我这边选择用一个width:1px
的input
用定位移动到旁边信息展示区下,用层级遮住。
<div class="text__strong">
密钥:<input id="googleSecuritKey" v-model="googleSecuritKey" type="text" style="width: 1px;border: none;position: relative; left: 2px; z-index: -1;"/>
{{googleSecuritKey}}
<span class="ui-btn ui-btn-default ui-btn-short float-r clearfix" @click="copy">复制</span>
</div>
解决科学计数法显示数字问题
参考出处:JavaScript中科学计数法转化为数值字符串形式
以下两种情况,JavaScript
会自动将数值转为科学计数法
表示
(1) 小于1且小数点后面带有6个0以上的浮点数值:
JavaScript 代码:
0.0000003 // 3e-7
0.00000033 // 3.3e-7
0.000003 // 0.000003
(2) 整数位数字多于21位:
JavaScript 代码:
1234567890123456789012 //1.2345678901234568e+21
1234567890123456789012.1 //1.2345678901234568e+21
123456789012345678901 //123456789012345680000
解决方案:
JavaScript 代码:
function toNonExponential(num) {
var m = num.toExponential().match(/\d(?:\.(\d*))?e([+-]\d+)/);
return num.toFixed(Math.max(0, (m[1] || '').length - m[2]));
}
toNonExponential(3.3e-7) // "0.00000033"
toNonExponential(3e-7) // "0.0000003"
toNonExponential(1.401e10) // "14010000000"
toNonExponential(0.0004) // "0.0004"
解析一下:
用.toExponential()
将数字转化为科学记数法表示,匹配正则表达式/\d(?:\.(\d*))?e([+-]\d+)/
,获取科学记数法中小数点后的字符及幂指数(e 后面的值),这样可以确定数字是几位小数。再用toFixed()
转换成数值表示。
大额数量转换
需求:
- 数量保持最多5个字符。
- 当数量<1,展示为0.003
- 当数量为1-1000,展示为1.234,12.34,123.4
- 当数量>1000,带上单位K,展示为1.54K,15.4K,154K
- 当数量>1000000时,带上单位M,展示为1.23M,12.3M,123M
- 数值采用向下取数展示的方式。如实际数量为15345,则展示为15.3K
项目中使用vue
过滤器做的处理:
export default (vol) => {
const val = parseFloat(vol) + '';
if (isNaN(val)) return vol;
let num = val.indexOf('.') ? val.split('.')[0].length : val.length;
const getFiv = function(v) {
let a = v.indexOf('.') ? v.substring(0, 5) : v;
let b = a.replace(/[.]$/, '');
return b;
};
if (num < 4) {
let v = val + '';
return getFiv(v);
} else if (num < 7) {
let v = val / 1000 + '';
return getFiv(v) + 'K';
} else {
let v = val / 1000000 + '';
return getFiv(v) + 'M';
}
};
可以抽取方法的,调整5相关,可以获取指定位数的缩写。
含有变量的正则表达式
value = value.replace(new RegExp(`^(\\-)*(\\d+)\\.(\\d{${count}}).*$`), '$1$2.$3');//只能输入count位小数
比如count
为4
:
value = value.replace(/^(\-)*(\d+)\.(\d{4}).*$/, '$1$2.$3');//只能输入4位小数
Blob
文件下载 借鉴
把请求
responseType
设置为blob
,在response.body
中拿数据(例子中使用了封装过的axios
,data处理过);const { data } = await http({ method: 'POST', headers: defaultHeaders, url: ..., responseType: 'blob', data: ... });
把接受的
data
处理成blob
对象,关于Bloblet blob = new Blob([data], { type: data.type });
以下来自MDN
语法 | 参数 |
---|---|
var aBlob = new Blob( array, options ); | array 是一个由ArrayBuffer , ArrayBufferView , Blob , DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob 。DOMStrings 会被编码为UTF-8 。 |
options 是一个可选的BlobPropertyBag 字典,它可能会指定如下两个属性: | |
- type ,默认值为 "",它代表了将会被放入到blob 中的数组内容的MIME 类型。 | |
- endings ,默认值为"transparent ",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: "native ",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent ",代表会保持blob中保存的结束符不变 |
创建
url
//URL.createObjectURL()方法会根据传入的参数创建一个指向该参数对象的URL. 这个URL的生命仅存在于它被创建的这个文档里. 新的对象URL指向执行的File对象或者是Blob对象.
let url = window.URL.createObjectURL(blob);
let fileName = '分析师列表.xlsx';
创建
a
标签实现自动下载或者手动下载if ('download' in document.createElement('a')) { const a = document.createElement('a'); a.href = url; a.download = fileName; a.style.display = 'none'; document.body.appendChild(a); a.click(); URL.revokeObjectURL(a.href); document.body.removeChild(a); } else { navigator.msSaveBlob(blob, fileName); }
日期格式化
RegExp.$1...$9
属性用于返回正则表达式模式中某个子表达式匹配的文本。正则表达式中每个小括号内的部分表达式就是一个子表达式。
注意:这里的RegExp是全局对象,RegExp.$1...$9
是全局属性。当执行任意正则表达式匹配操作时,JavaScript会自动更新全局对象RegExp上的全局属性,用以存储此次正则表达式模式的匹配结果。当再次执行正则表达式匹配时,RegExp上的全局属性又会更新,覆盖掉之前的存储数据,以反映本次正则表达式模式的匹配结果。
function formatDate(date, fmt) {
let fmtstr = fmt; //* 初始化一个结果赋值,由于结果字符串是对应格式化fmt的,这里逐个替换完成 如:年替换y
let dateObj = new Date(date);
if (!date) return;
const o = {
'M+': dateObj.getMonth() + 1, // * 月 从 0 开始要加 1
'd+': dateObj.getDate(), // * 日
'h+': dateObj.getHours(), // * 时 24H制
'm+': dateObj.getMinutes(), // * 分
's+': dateObj.getSeconds(), // * 分
'S+': dateObj.getMilliseconds(), //* 毫秒 常用在倒计时
'q+': Math.floor((dateObj.getMonth() + 3) / 3), //* 季
};
// ? 如果fmt中包含年份的需求
if (/(y+)/.test(fmt)) {
fmtstr = fmtstr.replace(RegExp.$1, (dateObj.getFullYear() + '').substr(4 - RegExp.$1.length()));
}
for (let k in o) {
// * 这里不要忘了() 正则分区
if (new RegExp(`(${k})`).test(fmt)) {
// *考虑: 月日时分秒 最多两位
// *如果只给一个标识位 则引用匹配的默认值,不用考虑补0
// *否则规范化显示考虑补0,从两位数考虑 0012 009 发现 取补完0后的字符串最后几位就好了 字符串原本有两位就从2位置取(起始是0,subtr包含起始位置) 1位也是同理 直接去想我感觉我是想不到这里 我就想直接写-2 -3了 哈哈
let padZero = k.indexOf('S') > -1 ? '000' : '00'; // *毫秒可以取三位 取两位
fmtstr = fmtstr.replace(
RegExp.$1,
RegExp.$1.length === 0 ? o[k] : `${padZero}${o[k]}`.substr(('' + o[k]).length, RegExp.$1.length)
);
}
}
return fmtstr;
}
一般网上搜到的 for
循环里
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
然而在处理三位数毫秒时001
会被处理成01
是不准的。
深拷贝
// 获取变量类型
function getType(el) {
//? 注意: null 返回 Null
return Object.prototype.toString.call(el).replace(/^\[object\s*(\S+)\]$/, '$1');
}
/**
* deepClone 深拷贝
* @param {object} obj 需要克隆的对象
* @param {array} cache 克隆过得对象,解决循环调用的无尽循环
*/
function deepClone (obj, cache = []) {
// 基本类型
if (typeof obj !== 'object' || obj === null ) {
return obj;
};
// 对象 === 对象 ? 是的 因为这里拷贝过得的对象存储时是引用关系,所以比较结果为true
let item = cache.filter(e => e.origin === obj)[0];
if (item) return item.copy;
let type = getType(obj);
let copy = type === 'Array' ? [] : {};
cache.push({
origin: obj,
copy
});
switch (type) {
case 'Error':
copy = new Error(obj);
break;
case 'RegExp':
copy = new RegExp(obj);
break;
case 'Date':
copy = new Date(obj)
break;
case 'Array':
case 'Object':
// 对象类型
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const element = obj[key];
copy[key] = deepClone(element, cache);
}
}
break;
default:
break;
}
return copy;
}
let cloneObj = deepClone(obj);
obj.number = 77;
obj.obj.s = obj;
// console.log(obj)
console.log(deepClone(obj))
scrollTop 无效?
页面指定DTD,即指定了DOCTYPE时,使用document.documentElement。
页面没有指定DTD,即没指定DOCTYPE时,使用document.body。
DTD 简介 DTD全称为,Document Type Definition,中文翻译为文档类型定义,是一套为了进行程序间的数据交换而建立的关于标记符的语法规则。 文档类型定义(DTD)可定义合法的XML文档构建模块。
document.documentElement.scrollTop = document.body.clientHeight; //滚动到底
纯函数 (Pure Function)
纯函数是指不依赖于且不改变它作用域之外的变量状态的函数。
ES6及以上常用的方法
Array.from()
Array.from()
方法从一个类似数组或可迭代对象中创建一个新的数组实例。
Array.from(arrayLike[, mapFn[, thisArg]])
- 第一个必选参数 类数组对象 - 每个元素的回调函数 - `this`对象
- 返回新数组
常见用法,不多说:
Array.from('string'); // ["s", "t", "r", "i", "n", "g"]
Array.from({a: 'a', b: 'b'}); // []
Array.from({1: 'a', 2: 'b'}); // []
Array.from([1, 2, 3], x => x + x)); // [2, 4, 6]
Array.from()
可以通过以下方式来创建数组对象:
- 伪数组对象(拥有一个
length
属性和若干索引属性的任意对象) - 可迭代对象(可以获取对象中的元素,如 Map和 Set 等)
拥有一个 length
属性这是我一直忽略的,这一点还是蛮有技巧性的,有时候能简化不少步骤
先看使用中的多种情况:
Array.from({1: 'a', 2: 'b', length: 2}); // [undefined, "a"]
Array.from({1: 'a', 2: 'b', length: 3}); // [undefined, "a", "b"]
Array.from({a: 'a', b: 'b',length: 3}); // [undefined, undefined, undefined]
还算比较智能。
看一下应用,来自Daily-Interview-Question2019-04-16的面试题:
第 55 题:某公司 1 到 12 月份的销售额存在一个对象里面,如下:{1:222, 2:123, 5:888},请把数据处理为如下结构:[222, 123, null, null, 888, null, null, null, null, null, null, null]。
我最开始直接来了个基本的遍历法...还在new Array(13)
或者[].length=13
简化版:
// 13长度的数组对应进去保持了key与索引一致,最终去除掉第一个元素就好
Array.from({1:222, 2:123, 5:888, length: 13}).slice(1).map(e => e || null);
let obj = {1:222, 2:123, 5:888};
Array.from({length: 12}).fill(null).map((e, index) => obj[index +1] || null);
相比起来,Array.fill()
没有什么容易忽略的地方。
未完待续
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。