面試題總結2-大廠

1.document.parentNode和document.parentnode的區別?(騰訊)

document:文檔對象,最外層
parentNode: 父節點屬性,document沒有父節點,document.parentNode = null
parentnode:document沒有parentnode這個屬性, document.parentnode = undefined

當前對象有這個屬性,但是目前這個屬性沒有值,則爲null
若當前對象連這個屬性都沒有,則爲undefined

2. 下面代碼能否實現點擊某個按鈕,body的背景色改爲按鈕對應的顏色,若不能,如何改進(騰訊)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    html,
    body {
      height: 100%;
      overflow: hidden;
    }

    button {
      padding: 5px 10px;
      cursor: pointer;
    }
  </style>
</head>

<body>
<!---->
<button value="red"></button>
<button value="green"></button>
<button value="blue"></button>

<script>
  var body = document.querySelector('body'),
    buttons = document.querySelectorAll('button'),
    arr = ['red', 'green', 'blue']
  for (var i = 0; i < buttons.length; i++) {
    buttons[i].onclick = function () {
      body.style.background = arr[i]
    }
  }
</script>
</body>

</html>

答案當然是不能,因爲通過var定義的變量,在for循環中的i是全局的,變量提升、3次循環過後,i=3,因爲點擊每個都相當於點擊最後一個。

優化

  1. 給元素對象添加自定義屬性
for (var i = 0; i < buttons.length; i++) {
  var item = buttons[i]
  //=>在循環的時候,把每一個按鈕的索引賦值給當前按鈕(元素對象)的myIndex自定義屬性
  item.myIndex = i 
  item.onclick = function () {
    // this => 當前點擊的這個按鈕
    body.style.background = arr[this.myIndex]
  }
}

  1. 利用閉包
// 都是利用閉包的機制去解決的
for (var i = 0; i < buttons.length; i++) {
  buttons[i].onclick = (function (i) {
    return function anonymous() {
      body.style.background = arr[i]
    }
  })(i)
}
  1. var換爲let

如果代碼塊中出現了 let/const/function 則當前代碼塊會產生一個 塊級上下文(詞法/塊級作用域) => 私有的上下文

let的方法和閉包的方法原理類似,都是每一輪循環產生一個私有的作用域,(LET塊級作用域),保存住當前循環i的值,以供後期調用。

var body = document.querySelector('body'),
  buttons = document.querySelectorAll('button'),
  arr = ['red', 'green', 'blue']
for (let i = 0; i < buttons.length; i++) {
	// 私有的塊級上下文
    // 循環幾次會產生幾個塊級上下文
  buttons[i].onclick = function () {
    body.style.background = arr[i]
  }
}

後期真實項目中推薦大家使用自定義屬性方法。不會產生那麼多不銷燬的私有作用域。

  1. forEach 方法

buttons 不是 Array對象,只是類數組,不能直接使用forEach方法,因此需要用call()執行

var body = document.querySelector('body'),
  buttons = document.querySelectorAll('button'),
  arr = ['red', 'green', 'blue']
[].forEach.call(buttons, (items, index) = > {
  item.onclick = function () {
    body.style.background = arr[i]
  }
})

3. let 和 var的區別

  1. let沒有變量提升(但是在詞法解析階段也能得知某個變量是否是私有變量)
  2. let不允許在相同的作用域下重複聲明
  3. let解決了JS中的暫時性死區問題
  4. let創建的全局變量沒有給window設置對應的屬性
  5. let會產生塊級作用域

    詳情請戳:JavaScript中let和var區別詳解
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章