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区别详解