<body> <ul> <li>test1</li> <li>test2</li> <li>test3</li> <li>test4</li> <li>test5</li> <li>test6</li> <li>test7</li> <li>test8</li> <li>test9</li> <li>test10</li> </ul> <script> var lis = document.querySelectorAll('ul li'); for(var i = 0, len = lis.length; i < len; i++) { lis[i].addEventListener('click', function () { console.log(i); }, false); } </script> </body>
你運行一下代碼會發現,無論你點擊哪個列表,控制台都是輸出10。這是因為var聲明的變量是函數作用域的,而不是塊級作用域的。也就是說,for循環10次,每次都是改變同一個i,所以它的值會從0一直加到10。還有個問題是閉包導致的,閉包保存的是外部變量的引用,而不是值。也就是說,循環10次監聽器創建了10 個閉包,它們里面的i引用的是同一個啊。所以全部都指向了10.
要解決這個問題有兩種方法。一種是使用ES6的let來替代 var i = 0 里面的var, 因為let支持塊級作用域。改成如下就正常了。
for(let i = 0, len = lis.length; i < len; i++) { lis[i].addEventListener('click', function () { console.log(i); }, false); }
還有一種方法,就是很多經典書本都提到的,使用立即執行函數來切斷閉包對外部變量i的引用:
for(var i = 0, len = lis.length; i < len; i++) { (function (i) { lis[i].addEventListener('click', function () { console.log(i); }, false); })(i) }
當然啦,如果對閉包不是很熟練,還可以通過事件委托來避開這個陷阱哈,代碼如下:
var ul = document.querySelector('ul'); var lis = document.querySelectorAll('ul li'); ul.addEventListener('click', function (e) { var target = e.target; if(target.nodeName.toLowerCase() === 'li') { console.log([].indexOf.call(lis, target)); } }, false);
使用了事件委托,減少了監聽器的綁定(只對列表的父親元素監聽),這種方法說不定還會加分呢。哈哈,我當時就是用這種方法來實現的,面試官可能覺得我的解法有點不尋常、頓時一臉蒙B,甚至還一度懷疑 console.log([].indexOf.call(lis, target)) 這段代碼是不是有問題。直到后來我直接在他的筆記本跑了一遍,他才相信是正確的。
-
下面的代碼有內存泄漏嗎
var user = {name: 'tom', age: 20, gender: 'male'} var test = document.getElementByid('test') test.onclick = function() { test.innerHTML = user.name; } // ...后面還有很多其他操作,最后把user對象釋放掉 user = null; // 釋放對象 - 實現一個算法,尋找字符串中出現次數最少的、並且首次出現位置最前的字符
如"cbaacfdeaebb",符合要求的是"f",因為他只出現了一次(次數最少)。並且比其他只出現一次的字符(如"d")首次出現的位置最靠前。 - http和tpc的關系,以及什么是https
- Node的特點(優點和缺點)
- 你在騰訊和網易實習期間學到的東西?
-
未來三年的職業規划
至於二面的問題都不是很難,下面簡單的來看一下:
-
第1題,基本類型(number, string, boolean, null, undefined, symbol)是在棧的,而其他的引用類型都是在堆的。垃圾回收是采用了計數引用法(如果兩個對象之間存在循環引用時,會有內存泄漏,因為計數無法變為0 )
-
第2題,有內存泄漏,這是閉包本身的問題。完全消除閉包的內存泄漏是不現實的,但是,如果采用下面的方法可以減少內存泄漏:
var user = {name: 'tom', age: 20, gender: 'male'} var test = document.getElementByid('test') (function (name) { test.onclick = function() { test.innerHTML = name; } })(user.name); user = null; -
第3題算法題,也不很難,大家可以自己試試去實現 ,如果做不出來的再到評論求助啦,這里就不貼出代碼了。
-
第4題,考察了計算機網絡的tcp三次握手以及http的請求頭等。https是使用安全套接字進行加密的,可以說HTTPS = SSL + HTTP。
-
第5題,Node的特點是異步非IO阻塞、適合高並發,但不適合密集型計算
-
第6、7題都是主觀題,可以隨便吹一下水便好。
因為當時已經是飯點時間,面試官也有點急着去吃飯,就沒有再問我問題了。
