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
,因爲點擊每個都相當於點擊最後一個。
優化
- 給元素對象添加自定義屬性
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]
}
}
- 利用閉包
// 都是利用閉包的機制去解決的
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = (function (i) {
return function anonymous() {
body.style.background = arr[i]
}
})(i)
}
- 把
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]
}
}
後期真實項目中推薦大家使用自定義屬性方法。不會產生那麼多不銷燬的私有作用域。
- 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的區別
- let沒有變量提升(但是在詞法解析階段也能得知某個變量是否是私有變量)
- let不允許在相同的作用域下重複聲明
- let解決了JS中的暫時性死區問題
- let創建的全局變量沒有給window設置對應的屬性
- let會產生塊級作用域
…
詳情請戳:JavaScript中let和var區別詳解