大家学习期间一定要弄清楚细节。
首先从面试题开始吧。题目来源 https://juejin.im/post/5aba6cff6fb9a028c14a7df1
题目一
alert(a)
a();
var a = 3;
var a = function() {
alert(10)
}
alert(a)
a = 6;
a();
请问输出什么?
这个我一看就知道靠的是变量提升,而这时牢记一句话函数比变量优先提升。但我没好好理解这局话,犯了个错误。
错误示范:
这是我刚开始以为的代码执行顺序
var a = function() {
alert(10);
}
var a;
alert(a)
a();
a = 3;
alert(a)
a = 6;
a();
正确示范:
var a;
var a = function() {
alert(10);
}
alert(a)
a();
a = 3;
alert(a)
a = 6;
a();
这才是真正的函数比变量优先提升。函数在变量后面声明。再来分析输出结果:
第一次alert(a),可以看到a这时是function,所以alert了整个函数。a();自然就是执行函数,alert(10);。这时a被赋予了3,所以第二个alert(a),变成alert(3)。最后a被赋予了6,a不是函数,自然执行不了,所以控制台会报错”a is not a function“。
题目二
想给ul下面的li加上点击事件,点击哪个li,就显示li的innerHTML,那么script标签怎么写?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul id="ul-test">
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>
</body>
通常的想法是给li addEventListener,但这有两个问题注册的事件过多,影响性能和要求太多内存。另外就是如果新增li,就没办法响应了。
解决这个问题要求:事件代理(事件委托)出马。
先来上一段文字解析,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。在代码就是只要监听ul-test就好了。
<script type="text/javascript">
let ul = document.querySelector('#ul-test')
ul.addEventListener('click', function(e) {
let target = e.target
if (target.tagName.toLowerCase() === 'li') {
alert(target.innerHTML)
}
})
</script>
题目三
在ul下新增10个li
常规做法如下,很明显缺点是操作DOM次数过多。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul id="ul-test">
</ul>
</body>
<script>
let ul = document.querySelector('#ul-test')
for (let i = 0; i < 10; i++) {
let li = document.createElement('li')
li.innerHTML = i
ul.appendChild(li)
}
</script>
</html>
改良
直接拼接我们所需的字符串,通过一次innerHTML就可以达到目的
<script>
let ul = document.querySelector('#ul-test')
let _html = ''
for (let i = 0; i < 10; i++) {
_html += '<li>' + i + '</li>'
}
ul.innerHTML = _html
</script>
实现对象深拷贝
function isObj(obj) {
return (Object.prototype.toString.call(obj) === '[object Object]')
}
function deepClone(obj) {
if (!isObj(obj)) return
let res = {}
for (let e in obj) {
isObj(e) ? deepClone(e) : res[e] = obj[e]
}
return res
}
let test = {2: 34, 3: {2:4}, 4: 5}
deepClone(test)
主要是 (Object.prototype.toString.call(obj) === ‘[object Object]’)这部分经常忘记。在jQuery中有个extend方法也能实现这个功能。