嗯,上次寫blog已是幾周前的事情了,其實已經積攢了不少小問題須要記錄和分享了。可是在8月底,VK我一次經歷了了攜程、拼多多、騰訊、網易等多輪面試轟炸,忙得不可開交,有喜有憂的同時,仍是趕快記錄了不足,把一些充滿迷惑性的問題繼續記錄和學習。javascript
JavaScript老是給人以驚喜,學習不止,進步不斷,今天繼續補充JS容易搞錯的幾道筆試/面試題,爲了秋招繼續努力,歡迎一塊兒爲秋招努力的小夥伴共勉html
系列筆記:前端
1.VK的秋招前端奇遇記(一)java
2.VK的秋招前端奇遇記(二)node
4.VK的秋招前端奇遇記(四)github
這是一道巨坑的題目算法
先看下不少博客、文章總結的一個關於循環的區別是怎麼說的編程
- map能夠作鏈式操做、forEach不能夠
- map有返回值,return、 forEach沒有返回值
- for循環不用擔憂兼容性問題,能夠break跳出循環,是基礎循環
- forEach不支持continue和break,是不能退出循環自己的。
上面這些比較,自己沒有什麼問題,可是當第三點和第四點結合的時候,就很容易讓人有個推論:
map是能夠跳出循環的,能夠提早中斷
然而,也的確有些面試官,認爲forEach不能break,map是能夠的跳出的
。 真的是這樣的?
首先,衆所周知,forEach
是不能用break提早中斷循環的,若是使用了,會直接報錯。好比如下:
var list = [1,2,3,4];
list.forEach(item => {
if(item === 2) {
break;
}
} )
複製代碼
可是,若是真的想要停止? 由於會報錯,這也提供給咱們一個思路,那就是用try..catch
把它保住,捕獲錯誤。 可是,我的認爲真是畫蛇添足,應該沒人會這麼用。就很少作討論了。
那麼map
能夠用break嗎?
很顯然,它也不行。因此若是有面試官問你,甚至告訴你"forEach和map的不一樣,forEach不能夠停止"時,你真的能夠大膽回擊:
Array.prototype.map
實現break,也是徹底不可能的請問如下程序中,person1
和person2
哪一個是Person的實例?其__proto__
分別指向誰?
function Person(name) {
this.name = name;
return {name: name}
}
var person1 = new Person('sam');
var person2 = Person('Lily')
複製代碼
person1和person2都不是Person的實例
它們的'__proto__'指向Object
複製代碼
這題題目的關鍵就是理解new
的過程,這也是常見的面試題之一了。若是遇到關鍵字new
,那麼,函數就不僅僅是一個函數了:
this
this.name = name
this
固然,這裏簡化了這個過程,可是核心是這幾步。 可是若是在隱式返回this
以前,提早返回了一個對象,那麼就會退出函數了。 要知道,只有這個this
纔是實例自己,它的__proto__
才指向構造函數,若是不能把this
返回出去,那麼一切都是徒勞的。所以,這裏不管是否new
,都返回的是一個新對象{}
。
這裏,本身當時回答的很差,就引用別人博客整理的內容啦.
function fn1() {
var obj = {name: 'hanzichi', age: 10};
}
function fn2() {
var obj = {name:'hanzichi', age: 10};
return obj;
}
var a = fn1();
var b = fn2();
複製代碼
fn1中定義的obj爲局部變量,而當調用結束後,出了fn1的環境,那麼該塊內存會被js引擎中的垃圾回收器自動釋放;在fn2被調用的過程當中,返回的對象被全局變量b所指向,因此該塊內存並不會被釋放。
標記清除:
定義和用法:當變量進入環境時,將變量標記"進入環境",當變量離開環境時,標記爲:"離開環境"。某一個時刻,垃圾回收器會過濾掉環境中的變量,以及被環境變量引用的變量,剩下的就是被視爲準備回收的變量。
到目前爲止,IE、Firefox、Opera、Chrome、Safari的js實現使用的都是標記清除的垃圾回收策略或相似的策略,只不過垃圾收集的時間間隔互不相同。
引用計數:
定義和用法:引用計數是跟蹤記錄每一個值被引用的次數。
基本原理:就是變量的引用次數,被引用一次則加1,當這個引用計數爲0時,被視爲準備回收的對象。
垃圾回收器週期性運行,若是分配的內存很是多,那麼回收工做也會很艱鉅,肯定垃圾回收時間間隔就變成了一個值得思考的問題。
IE6的垃圾回收是根據內存分配量運行的,當環境中的變量,對象,字符串達到必定數量時觸發垃圾回收。垃圾回收器一直處於工做狀態,嚴重影響瀏覽器性能。
IE7中,垃圾回收器會根據內存分配量與程序佔用內存的比例進行動態調整,開始回收工做。
說實話,這一塊,本身沒有很好的整理,可是目前準備秋招和畢設,沒有更多的經歷,只能待有空再深刻學習研究了。
請將如下表格,按年齡進行排序,使用原生JS,不容許使用任何第三方工具。
<table>
<thead>
<tr>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
<tr>
<td>張三</td>
<td>17</td>
</tr>
<tr>
<td>李四</td>
<td>43</td>
</tr>
<tr>
<td>王五</td>
<td>22</td>
</tr>
<tr>
<td>小劉</td>
<td>9</td>
</tr>
<tr>
<td>黃三</td>
<td>20</td>
</tr>
</tbody>
</table>
複製代碼
這個其實很easy了,只是我在寫的時候,仍是調試了好幾回,這裏主要兩點:
document.getElementsBytagNames
選擇的對象,在dom的映射機制下,是雙雙綁定的;dom.appendChild()
方法,要保證參數是node節點。Array.sort()
方法,注意,只能用在Array上。var sortByAge = function () {
var tbody = document.getElementsByTagName('tbody')[0];
var items = tbody.getElementsByTagName('tr');
let arrayI = Array(...items); //將類數組轉化爲數組,使用sort方法
arrayI.sort((a,b)=> {
let ageA = a.getElementsByTagName('td')[1].innerText;
let ageB = b.getElementsByTagName('td')[1].innerText;
return ageA - ageB;
})
for(let i = 0; i<items.length; i++) {
tbody.appendChild(arrayI[i]); //依次插入,這裏arrayI的每個元素都是原來的dom映射過來的實例。因此並非「創造」出了複製品,而是從新排序了
}
}
sortByAge();
複製代碼
一天24小時,咱們將其折爲每30分鐘爲一段,這樣一天共有48段。咱們用1表示這段時間有效,0表示無效,好比10...
表示開始時間爲00:00
持續了半個小時,技術時間爲00:30
。111001..
則表示00:00~01:30
02:30~03:00
兩個時間段。
要求寫一個函數,對時間碼進行轉換:
輸入:110100000000000000000000000000000000000000000000
輸出: ["00:30~01:30", "01:00~02:00"]
這個是我視頻面試時的一道編程題,因爲時間緊,面對面試官有點小壓力,因此就用了比較笨的方法實現了,後來也沒有從新思考和優化,有好的思路和簡單的方法的小夥伴歡迎交流。
如下思路:
startTime
;若是不是第一次,進行time
累加time
值進行累加,計算endTime
,並將時間段push到數組根據上面思路,代碼以下:
function timeTransfer(str) {
var flag = false, //flag,判斷是否第一次爲1
time = 0, //時間記錄值
n = str.length,
startTime, //開始時間
startHour, //開始的小時
startMin, //開始的分鐘
endTime, //結束時間
endHour, //結束的小時
endMin, //結束的分鐘
retTime = []; //最終返回的數組
for(let i = 0 ; i < n; i++) {
if(str[i] === '1') {
if(flag === false) { //判斷是否爲第一個1,若是是,根據i設定開始時間
startHour = parseInt(i/2);
startMin = i % 2 ? 0:30;
startTime = `${startHour > 9? startHour: '0' + startHour}:${startMin > 9 ? startMin : '0' + startMin}`;
flag = true; //置位 flag
}
time += 0.5; //時間累加
if(i === n-1) { //若是已經遍歷到最後,那麼計算結束時間(當str的末尾爲1時,須要處理)
endHour = startHour + parseInt(time);
endMin = startMin + (time % 2 ? 0 : 30);
endTime = `${endHour > 9 ? endHour : '0' + endHour}:${endMin > 9 ? endMin : '0' + endMin}`;
retTime.push(`${startTime}~${endTime}`);
}
} else if (str[i] === '0') {
if(flag === false) { //若是爲flase,表明前面不是1,繼續下次循環
continue;
} else { //不然,計算結束時間
flag = false;
endHour = startHour + parseInt(time);
endMin = startMin + (time % 2 ? 0 : 30);
endTime = `${endHour > 9 ? endHour : '0' + endHour}:${endMin > 9 ? endMin : '0' + endMin}`;
retTime.push(`${startTime}~${endTime}`);
}
}
}
return retTime;
}
複製代碼
以上程序,是跑通了的,雖然有點笨,可是勉強知足要求。