你盼世界,我盼望你无bug
。Hello 你们好!我是霖呆呆!javascript
呆呆每周都会分享七道前端题给你们,系列名称就是「DD每周七题」。css
系列的形式主要是:3道JavaScript
+ 2道HTML
+ 2道CSS
,帮助咱们你们一块儿巩固前端基础。前端
全部题目也都会整合至 LinDaiDai/niubility-coding-js 的issues
中,欢迎你们提供更好的解题思路,谢谢你们😁。java
一块儿来看看本周的七道题吧。node
(题目来源:github.com/30-seconds/…)css3
首先介绍一下题目的意思吧😄,案例🌰以下:git
const mask = (str, maskChar = '#') => {
// 代码 } console.log(mask('123456')); // '##3456' console.log(mask('lindaidai')); // '#####idai' 复制代码
这道题的难度应该没有那么大,处理方式也有不少。呆呆这边主要是讲解一下如何使用padStart
来实现的。github
简单介绍一下padStart
方法吧,它是ES8
新增的实例函数,与它做用差很少的还有一个叫padEnd
的函数:web
String.prototype.padStart
String.prototype.padEnd
「做用」:容许将空字符串或其余字符串添加到原始字符串的开头或结尾。浏览器
「语法」:
padStart(targetLength, [padString])
复制代码
targetLength
: 必填,当前字符串须要填充到的目标长度。若是这个数值小于当前字符串的长度,则返回当前字符串自己。
padString
: 可选,填充字符串。若是字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其余部分会被截断,此参数的缺省值为
" "
。
例如:
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab' 复制代码
哈哈,另外想要了解如何实现一个padStart
的小伙伴能够看呆呆以前一篇文章哟:DD每周前端七题详解-第二期
「言归正传」,让咱们回到这道题目哈,首先让咱们来处理一下输入参数边界的状况,例如输入的str
不存在或者长度小于4
的时候:
const mask = (str, maskChar = '#') => {
if (!str || str.length <= 4) return str; } 复制代码
其次,咱们能够只保留住str
的末尾四个字符,而后使用padStart
将这四个字符填充至str.length
便可,以下:
const mask = (str, maskChar = '#') => {
if (!str || str.length <= 4) return str; return str.slice(-4).padStart(str.length, maskChar); } 复制代码
slice
不会影响本来的字符串
padStart
填充便可
「介绍一下NaN」:
NaN
属性是表明非数字值的特殊值,该属性用于指示某个值不是数字;
NaN
是不等于
NaN
的,即
NaN === NaN
的结果是
false
;
Object.is()
来比较两个
NaN
结果是
true
,即
Object.is(NaN, NaN)
的结果是
true
;
typeof NaN
为
"number"
;
parseInt()
和
parseFloat()
在不能解析指定的字符串时就返回这个值;
isNaN
来判断一个变量是否是
NaN
,它是
JS
内置对象
Number
上的静态方法。
(关于第三点,你们能够看一下我以前的一篇文章哟,里面的「第二补:JS类型检测-Object.is()和===的区别
」有提到:读《三元-JS灵魂之问》总结,给本身的一份原生JS补给(上))
「实现一个isNaN」:
对于isNaN
的polyfill
实现起来就比较简单了,只须要利用NaN
不等于它自身的这一点便可:
const isNaN = v => v !== v;
复制代码
~2 = -3
?接下来,分享一道与JavaScript
原生无关的题目吧,主要也是看到群里有小伙伴问了关于按位取反~
的用法,这边统一科普一下,😁。
正常一个数字,例如1
和2
,或者-1
和-2
。
若是咱们对它们进行按位取反的话,结果会是这样:
~1 = -2
~2 = -3
~-1 = 0
~-2 = 1
看不懂不要紧,让咱们来一步步看看实现的过程哈。
在这里实际上是分了「正数和负数」的,由于符号不一样取反的过程也会不一样。
先让咱们来看看正数的按位取反。
好比先看看~1 = -2
,过程以下:
「1. 十进制转为二进制原码」
首先将十进制的1
转化为二进制原码为:0000 0001
「2. 二进制原码按位取反」
以后将原码按位取反:
也就是将0000 0001
=> 1111 1110
(取反应该知道啥意思吧?就是0
换成1
,1
换成0
)
「3. 取反后的二进制转为原码」
再将取反后的二进制码转为原码二进制:
也就是将1111 1110
=> 1000 0010
这里你估计看着都点懵了,当咱们将「取反后的二进制」转为「原码二进制」的时候,实际上是有如下两步的:
1
,这个第一位咱们称之为
「符号位」,若是是
1
的话就表示即将要转成的数是一个负数,若是是
0
的话表示即将要转的数是一个正数,这个符号位是不能动的;在这里咱们能够看到
1111 1110
的第一位是
1
,因此表示即将要转的数是一个负数,同时咱们不动它。
+1
。因此会有这么两个过程:
1111 1110
=>
1000 0001
1000 0001
=>
1000 0010
(这步是对上一步的结果
+1
,由于上一步的最后一个数是
1
,因此它再加上
1
就须要向前进一位了,所以变成了
1000 0010
)
「4. 将原码二进制转为十进制」
最后一步就是将咱们前面获得的1000 0010
这个二进制转化为十进制了。
第一位符号位,是1
,则表示是个负数,因此结果为-2
。
OK👌,搞懂了这个步骤以后再让咱们本身来转换一下~2 = -3
吧:
1. 0000 0010 2. 1111 1101 3. 1000 0011 4. -3 复制代码
「正数按位取反总结」
负数的按位取反和上面就有些不同了,主要是第二步和第三步调换一下顺序:
例如:~-1 =0
的转换过程:
「1. 十进制转为二进制原码」
这步和正数按位取反是同样的:
-1
=> 1000 0001
「2. 符号位保留,其他位取反+1」
转换过程:
1000 0001
=>
1111 1110
(取反)
1111 1110
=>
1111 1111
(取反后 + 1)
「3. 二进制原码按位取反」
将刚刚获得的再进行按位取反:
1111 1111
=> 0000 0000
「4. 二进制原码转为十进制」
0000 0000
=> 0
OK👌,如今本身来转换一下~-2 = 1
吧:
1. 1000 0010 2. 1111 1110 3. 0000 0001 4. 1 复制代码
这里没啥诀窍,关键就是要记住转换的过程而后不断的练习吧 😂。
另外关于~~
的用法还能够看呆呆的另外一篇文章哟《JS中按位取反运算符~及其它运算符》
insertAdjacentHTML
方法吗?这个方法是呆呆最近在看公司项目代码时了解到的,以前一直没有注意它。
首先对于它的用法:
「
insertAdjacentHTML()
」 方法将指定的文本解析为Element
元素,并将结果节点插入到DOM树中的指定位置。它不会从新解析它正在使用的元素,所以它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接使用innerHTML操做更快。
其次它的做用对象是一个元素element
,例如const container = document.getElementById('container')
语法上呢:
element.insertAdjacentHTML(position, text);
复制代码
position
:一个
DOMString
,也就是表示插入内容相对元素的位置,且必须是下面的字符串之一:
'beforebegin'
:元素自身的前面。
'afterbegin'
:插入元素内部的第一个子节点以前。
'beforeend'
:插入元素内部的最后一个子节点以后。
'afterend'
:元素自身的后面。
text
:是要被解析为HTML或XML元素,并插入到DOM树中的
DOMString
。
「案例」:
让咱们来看看它的用法,例如🌰如今有一个HTML
的结构为:
<div id="one">我是one</div>
复制代码
JavaScript
代码中加上这段话:
const one = document.getElementById('one');
one.insertAdjacentHTML('afterend', '<div id="two">我是two</div>'); 复制代码
如今最终的渲染结果就变成了这样:
<div id="one">我是one</div><div id="two">我是two</div>
复制代码
「工做上的用法」:
在项目中,主要能够应用于这样的场景:一个空的容器(你能够理解为一个div
),开始须要一个loading
的效果,在数据加载完毕以后,须要把loading
取掉且清空容器内的元素并以其它方式从新渲染出容器的内容。
这里呆呆就以定时器来模拟一下数据加载的过程,实现代码以下:
<body>
<div id="container"></div> </body> <script> const container = document.getElementById('container'); const loading = '<div id="loading">loading</div>'; // loading多是一个组件 container.insertAdjacentHTML('beforeend', loading); setTimeout(() => { container.innerHTML = '' }, 2000) </script> 复制代码
(固然,咱们不要为了刻意用而去用,适合本身的才是最好的)
「安全问题」:
使用 insertAdjacentHTML
插入用户输入的HTML内容的时候,须要转义以后才能使用。
例如:
const one = document.getElementById('one');
// 因为 encodeURI('<div id="two">我是two</div>')会被转译为: // %3Cdiv%20id=%22two%22%3E%E6%88%91%E6%98%AFtwo%3C/div%3E // 所以最终会被当成 "%3Cdiv%20id=%22two%22%3E%E6%88%91%E6%98%AFtwo%3C/div%3E"字符串渲染 one.insertAdjacentHTML('afterend', encodeURI('<div id="two">我是two</div>')); 复制代码
若是只是为了插入文本内容(而不是HTML节点),不建议使用这个方法,建议使用node.textContent
或者 node.insertAdjacentText()
。由于这样不须要通过HTML解释器的转换,性能会好一点。(这里是引用的MDN-insertAdjacentHTML上的内容)
insertAdjacentHTML
和insertAdjacentElement
的区别第二个参数的类型不一样, 前者接收的是是要被解析为HTML或XML元素的字符串
,然后者接收的是一个element
元素。
const one = document.getElementById('one');
one.insertAdjacentHTML('afterend', '<div id="two">我是two</div>'); const one = document.getElementById('one'); const two = document.createElement('div') two.innerHTML = '我是two'; one.insertAdjacentElement('afterend', two); 复制代码
实现效果以下:
先来看一下HTML
方面的代码:
<div id="container">
<div class="item item-1">1</div> <div class="item item-2">2</div> <div class="item item-3">3</div> <div class="item item-4">4</div> <div class="item item-5">5</div> <div class="item item-6">6</div> <div class="item item-7">7</div> <div class="item item-8">8</div> <div class="item item-9">9</div> </div> 复制代码
还有一些item
上的基础css
代码:
#container {
/* css代码 */ } .item { font-size: 2em; text-align: center; border: 1px solid #e5e4e9; } .item-1 { background-color: #ef342a; } .item-2 { background-color: #f68f26; } .item-3 { background-color: #4ba946; } .item-4 { background-color: #0376c2; } .item-5 { background-color: #c077af; } .item-6 { background-color: #f8d29d; } .item-7 { background-color: #b5a87f; } .item-8 { background-color: #d0e4a9; } .item-9 { background-color: #4dc7ec; } 复制代码
「方案一」:
第一种方案可使用浮动+百分比:
#container {
width: 150px; height: 150px; } .item { float: left; width: 33.33%; height: 33.33%; box-sizing: border-box; font-size: 2em; text-align: center; border: 1px solid #e5e4e9; } 复制代码
「方案二」:
还可使用flex
布局的方式:
#container {
width: 150px; height: 150px; display: flex; flex-wrap: wrap; } .item { width: 33.33%; height: 33.33%; box-sizing: border-box; font-size: 2em; text-align: center; border: 1px solid #e5e4e9; } 复制代码
「方案三」:
另外的话,也许还能够试试grid
?
#container {
display: grid; grid-template-columns: 50px 50px 50px; grid-template-rows: 50px 50px 50px; } .item { font-size: 2em; text-align: center; border: 1px solid #e5e4e9; } 复制代码
will-change
是CSS3
新增的标准属性,它的做用很单纯,就是"加强页面渲染性能"
,当咱们在经过某些行为触发页面进行大面积绘制的时候,浏览器每每是没有准备,只能被动的使用CPU去计算和重绘,因为事先没有准备,对于一些复杂的渲染可能会出现掉帧、卡顿等状况。
而will-change
则是在真正的行为触发以前告诉浏览器可能要进行重绘了,至关于浏览器把CPU拉上了,能从容的面对接下来的变形。
经常使用的语法主要有:
whil-change: scroll-position;
即将开始滚动
will-change: contents;
内容要动画或者变化了
will-transform;
transform相关的属性要变化了(经常使用)
注意:
will-change
虽然能够开启加速,可是必定要适度使用
hover
中,这样移出元素的时候就会自动
remove
掉
will-change
了
JS
添加了
will-change
,注意要及时
remove
掉,方式就是
style.willChange = 'auto'
知识无价,支持原创。
参考文章:
你盼世界,我盼望你无bug
。这篇文章就介绍到这里。
您每周也许会花48
小时的时间在工做💻上,会花49
小时的时间在睡觉😴上,也许还能够再花20
分钟的时间在呆呆的7道题上,日积月累,我相信咱们都能见证彼此的成长😊。
什么?你问我为何系列的名字叫DD
?由于呆呆
呀,哈哈😄。
喜欢「霖呆呆」的小伙还但愿能够关注霖呆呆的公众号 LinDaiDai
或者扫一扫下面的二维码👇👇👇。
我会不定时的更新一些前端方面的知识内容以及本身的原创文章🎉
你的鼓励就是我持续创做的主要动力 😊。
本文使用 mdnice 排版