DD每週前端七題詳解-第五期

DD每週前端七題詳解-第五期

系列介紹

你盼世界,我盼望你無bug。Hello 你們好!我是霖呆呆!javascript

呆呆每週都會分享七道前端題給你們,系列名稱就是「DD每週七題」。css

系列的形式主要是:3道JavaScript + 2道HTML + 2道CSS,幫助咱們你們一塊兒鞏固前端基礎。前端

全部題目也都會整合至 LinDaiDai/niubility-coding-jsissues中,歡迎你們提供更好的解題思路,謝謝你們😁。java

一塊兒來看看本週的七道題吧。node

正題

1、實現mask函數將"123456"轉爲"##3456",只保留最後四個字符

(題目來源: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填充便可

github.com/LinDaiDai/n…

2、介紹一下NaN並實現一個isNaN

介紹一下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:

對於isNaNpolyfill實現起來就比較簡單了,只須要利用NaN不等於它自身的這一點便可:

const isNaN = v => v !== v;
複製代碼

github.com/LinDaiDai/n…

3、按位取反,爲何~2 = -3?

接下來,分享一道與JavaScript原生無關的題目吧,主要也是看到羣裏有小夥伴問了關於按位取反~的用法,這邊統一科普一下,😁。

正常一個數字,例如12,或者-1-2

若是咱們對它們進行按位取反的話,結果會是這樣:

  • ~1 = -2
  • ~2 = -3
  • ~-1 = 0
  • ~-2 = 1

看不懂不要緊,讓咱們來一步步看看實現的過程哈。

在這裏實際上是分了正數和負數的,由於符號不一樣取反的過程也會不一樣。

1.1 正數按位取反

先讓咱們來看看正數的按位取反。

好比先看看~1 = -2,過程以下:

1. 十進制轉爲二進制原碼

首先將十進制的1轉化爲二進制原碼爲:0000 0001

2. 二進制原碼按位取反

以後將原碼按位取反:

也就是將0000 0001 => 1111 1110

(取反應該知道啥意思吧?就是0換成11換成0)

3. 取反後的二進制轉爲原碼

再將取反後的二進制碼轉爲原碼二進制:

也就是將1111 1110 => 1000 0010

這裏你估計看着都點懵了,當咱們將取反後的二進制轉爲原碼二進制的時候,實際上是有如下兩步的:

  1. 須要判斷取反後的二進制的第一個位是否是 1,這個第一位咱們稱之爲 符號位,若是是 1的話就表示即將要轉成的數是一個負數,若是是 0的話表示即將要轉的數是一個正數,這個符號位是不能動的;在這裏咱們能夠看到 1111 1110的第一位是 1,因此表示即將要轉的數是一個負數,同時咱們不動它。
  2. 而後將除了第一位之外其它位數取反並 +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. 十進制轉爲二進制原碼
  2. 二進制原碼按位取反
  3. 符號位保留,其他位取反+1
  4. 二進制原碼轉爲十進制

1.2 負數按位取反

負數的按位取反和上面就有些不同了,主要是第二步和第三步調換一下順序:

  1. 十進制轉爲二進制原碼
  2. 符號位保留,其他位取反+1
  3. 二進制原碼按位取反
  4. 二進制原碼轉爲十進制

例如:~-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中按位取反運算符~及其它運算符》

github.com/LinDaiDai/n…

4、知道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上的內容)

github.com/LinDaiDai/n…

5、insertAdjacentHTMLinsertAdjacentElement的區別

第二個參數的類型不一樣, 前者接收的是是要被解析爲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); 複製代碼

github.com/LinDaiDai/n…

6、實現九宮格佈局

實現效果以下:

先來看一下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; } 複製代碼

答案參考:github.com/haizlin/fe-…

github.com/LinDaiDai/n…

7、說說will-change

will-changeCSS3新增的標準屬性,它的做用很單純,就是"加強頁面渲染性能",當咱們在經過某些行爲觸發頁面進行大面積繪製的時候,瀏覽器每每是沒有準備,只能被動的使用CPU去計算和重繪,因爲事先沒有準備,對於一些複雜的渲染可能會出現掉幀、卡頓等狀況。

will-change則是在真正的行爲觸發以前告訴瀏覽器可能要進行重繪了,至關於瀏覽器把CPU拉上了,能從容的面對接下來的變形。

經常使用的語法主要有:

  • whil-change: scroll-position; 即將開始滾動
  • will-change: contents; 內容要動畫或者變化了
  • will-transform; transform相關的屬性要變化了(經常使用)

注意:

  • will-change雖然能夠開啓加速,可是必定要適度使用
  • 開啓加速的代價爲手機的耗電量會增長
  • 使用時遵循最小化影響原則,能夠對僞元素開啓加速,獨立渲染
  • 能夠寫在僞類中,例如 hover中,這樣移出元素的時候就會自動 removewill-change
  • 若是使用 JS添加了 will-change,注意要及時 remove掉,方式就是 style.willChange = 'auto'

github.com/LinDaiDai/n…

參考文章

知識無價,支持原創。

參考文章:

後語

你盼世界,我盼望你無bug。這篇文章就介紹到這裏。

您每週也許會花48小時的時間在工做💻上,會花49小時的時間在睡覺😴上,也許還能夠再花20分鐘的時間在呆呆的7道題上,日積月累,我相信咱們都能見證彼此的成長😊。

什麼?你問我爲何系列的名字叫DD?由於呆呆呀,哈哈😄。

喜歡霖呆呆的小夥還但願能夠關注霖呆呆的公衆號 LinDaiDai 或者掃一掃下面的二維碼👇👇👇。

img
img

我會不定時的更新一些前端方面的知識內容以及本身的原創文章🎉

你的鼓勵就是我持續創做的主要動力 😊。

本文使用 mdnice 排版

相關文章
相關標籤/搜索