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

DD每週七題-第一期

系列介紹

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

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

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

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

正題

1、Array(3)和Array(3, 4)的區別?

console.log(Array(3))
console.log(Array(3, 4))  console.log(new Array(3)) console.log(new Array(3, 4))  console.log(Array.of(3)) console.log(Array.of(3, 4)) 複製代碼

考察知識點:數組

  • Array()new Array()
  • Array()參數個數不一樣時的不一樣表現
  • Array.of()的做用

結果:瀏覽器

console.log(Array(3)) // [empty x 3]
console.log(Array(3, 4)) // [3, 4]  console.log(new Array(3)) // [empty x 3] console.log(new Array(3, 4)) // [3, 4]  console.log(Array.of(3)) // [3] console.log(Array.of(3, 4)) // [3, 4] 複製代碼

總結:編輯器

  • Array使不使用 new效果都是同樣的
  • Array方法,若是參數是一位的話,這個參數表示的是數組的長度,並建立此長度的空數組
  • Array方法,若是參數是多位的話則每個參數都是數組的一項,會按順序返回數組
  • Array.of()接收任意個參數,將按順序成爲返回數組中的元素,並返回這個新數組。

github.com/LinDaiDai/n…函數

2、請建立一個長度爲100,值爲對應下標的數組

// cool點的寫法:
[...Array(100).keys()]  // 其餘方法: Array(100).join(",").split(",").map((v, i) => i) Array(100).fill().map((v, i) => i) 複製代碼

後面兩種方法相信你們都能看到懂,也沒啥好說的了😄,讓咱們仔細看一下這個比較cool的寫法:ui

  • 使用Array(100)建立一個內容全爲empty的數組:[empty x 100]this

  • 使用keys()方法從數組建立一個包含數組鍵的可迭代對象:

    可迭代對象是否是讓你想到了generator,沒錯的,這裏的keys()Array.prototype上的方法,你們可能會把它和咱們以前用的比較多的Object.keys()搞混。

    說一下它的做用吧,它其實就像剛剛介紹的同樣,會建立一個可迭代對象,那麼小夥伴們應該知道,一個可迭代對象返回的數據會是這樣的:

    { value: 0, done: false }
    複製代碼

    value爲此次的返回值,done爲當前可迭代對象的邏輯塊是否執行完成。

    因此你會看到如下這段代碼是會這樣執行的:

    let it = Array(100).keys()
    console.log(it.next) // {value: 0, done: false} console.log(it.next) // {value: 1, done: false} console.log(it.next) // {value: 2, done: false} console.log(it.next) // {value: 3, done: false} 複製代碼
  • 至於[...arr]這個就是ES6的寫法了,轉化爲數組,固然你也能夠直接用Array.from()。這兩種方式都支持將可迭代對象轉換爲數組。

github.com/LinDaiDai/n…

3、實現 arr[-1] = arr[arr.length - 1]

這道題的意思是:提供一個createArr()方法,用此方法建立的數組知足arr[-1] = arr[arr.length - 1]

function createArr (...elements) {
 // ...代碼  return arr } var arr1 = createArr(1, 2, 3) console.log(arr1[-1]) // 3 console.log(arr1[-2]) // 2 複製代碼

解題思路:

其實對於這類題目,我首先想到的會是Object.defineProperty()或者Proxy。由於這裏涉及到了對數組值的獲取,顯然用Proxy是比較合適的。什麼?你問我爲何不用Object.defineProperty()?由於這個方法是針對於對象的某一個屬性的呀,對數組來講不合適。

因此對於這道題,咱們也許可使用Proxy代理每次傳入進來的下標,也就是重寫一下數組的get方法,在這個方法中咱們去處理這方面的邏輯,一塊兒來看看代碼吧😊:

function createArr (...elements) {
 let handler = {  get (target, key, receiver) { // 第三個參數傳不傳均可以  let index = Number(key) // 或者 let index = ~~key  if (index < 0) {  index = String(target.length + index)  }  return Reflect.get(target, index, receiver)  }  }  let target = [...elements] // 建立一個新數組  return new Proxy(target, handler) } var arr1 = createArr(1, 2, 3) console.log(arr1[-1]) // 3 console.log(arr1[-2]) // 2 複製代碼

注意點:

  • get接收到的第二個參數key表示的是數組下標,它是字符串形式,因此須要轉爲Number,固然方法有不少種了,使用Number()也能夠,使用~~雙非按位取反運算符也能夠。對比於Number()的好處就是Number(undefined)會轉換爲NaN;可是使用~~能保證一直是數字,~~undefined === 0。(什麼?你還不知道區別?那你得看霖呆呆的這篇文章了:JS中按位取反運算符~及其它運算符)

  • 接下來只須要判斷一下傳入進來的下標是否是小於0的,小於0的話加上數組的長度就能夠了

  • 而後返回index這一項使用的是Reflect.get(target, index)。什麼?爲何不直接用target[index]?固然這樣也能夠,對比target[index]的區別就是Reflect.get(target, index)若是傳入的target不是一個Object的話(數組也屬於對象),就會報一個類型錯誤TypeError,而target[index]返回的會是一個undefined。好比這樣:

    var obj = 5
    console.log(obj['b']) // undefined console.log(Reflect.get(obj, 'b')) // Uncaught TypeError: Reflect.get called on non-object 複製代碼

擴展點:

呆呆這邊主要是想擴展一下get的第三個參數receiver(接受者),在MDN上的解釋是:

若是target對象中指定了getterreceiver則爲getter調用時的this值。

來看個例子理解一下😊。

案例一

例如咱們開始有這麼一個對象:

var obj = {
 fn: function () {  console.log('lindaidai')  } } 複製代碼

如今使用Proxy來賦值到obj1中:

var obj = {
 fn: function () {  console.log('lindaidai')  } } var obj1 = new Proxy(obj, {  get (target, key, receiver) {  console.log(receiver === obj1) // true  console.log(receiver === target) // false  return target[key]  } }) obj1.fn() 複製代碼

能夠看到,receiver表示的是obj1這個新的代理對象,target表示的是被代理的對象obj

因此,receiver能夠表示使用代理對象自己

案例二

另外一種狀況,receiver也能夠表示是從其繼承的對象

var proxy = new Proxy({}, {
 get (target, key, receiver) {  return receiver;  } }) console.log(proxy.getReceiver === proxy) // true var inherits = Object.create(proxy) console.log(inherits.getReceiver === inherits) // true 複製代碼

這個案例中,我新建了一個空對象的代理對象proxy,使用proxy.getReceiver獲取它的receiver,發現它就是代理對象自己。

而若是我將這個代理對象做爲一個原型對象,建立出一個新的對象inherits,也就是實現了原型式繼承,那麼這時候receiver的值就是這個被繼承的對象inherits

總結

  • 可使用 Proxy代理,來改變每次獲取數組的值。
  • Proxyget中,第二個參數是字符串,即便傳入的是數組下標。
  • 對比於 Number()的好處就是 Number(undefined)會轉換爲 NaN;可是使用 ~~能保證一直是數字, ~~undefined === 0
  • 對比 target[index]的區別就是 Reflect.get(target, index)若是傳入的 target不是一個 Object的話(數組也屬於對象),就會報一個類型錯誤 TypeError,而 target[index]返回的會是一個 undefined
  • Proxyget中,第三個參數 receiver一般爲使用代理對象自己或從其繼承的對象。

github.com/LinDaiDai/n…

4、addEventListener和attachEvent的區別?

  • 前者是標準瀏覽器中的用法,後者 IE8如下
  • addEventListener可有冒泡,可有捕獲; attachEvent只有冒泡,沒有捕獲。
  • 前者事件名不帶 on,後者帶 on
  • 前者回調函數中的 this指向當前元素,後者指向 window

github.com/LinDaiDai/n…

5、addEventListener函數的第三個參數

第三個參數涉及到冒泡和捕獲,是true時爲捕獲,是false則爲冒泡。

或者是一個對象{passive: true},針對的是Safari瀏覽器,禁止/開啓使用滾動的時候要用到。

github.com/LinDaiDai/n…

6、文字單超出顯示省略號

div {
 width: 200px;  overflow: hidden;  white-space: nowrap;  text-overflow: ellipsis; } 複製代碼

github.com/LinDaiDai/n…

7、文字多行超出顯示省略號

div {
 width: 200px;  display: -webkit-box;  -webkit-box-orient: vertical;  -webkit-line-clamp: 3;  overflow: hidden; } 複製代碼

該方法適用於WebKit瀏覽器及移動端。

跨瀏覽器兼容方案:

p {
 position:relative;  line-height:1.4em;  /* 3 times the line-height to show 3 lines */  height:4.2em;  overflow:hidden; } p::after {  content:"...";  font-weight:bold;  position:absolute;  bottom:0;  right:0;  padding:0 20px 1px 45px; } 複製代碼

github.com/LinDaiDai/n…

後語

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

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

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

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

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

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

本文使用 mdnice 排版

相關文章
相關標籤/搜索