在簡書看到這篇面試題,結合作者的答案和個人的理解做了一下,因個人水平有限(不謙虛,確實很菜),如果個人做的有什麼不對的歡迎指出來,共同交流
作者:詩和元芳 連結:www.jianshu.com/p/e6efcd993… 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。
筆試
題目一
<div id="d">
<div id = "a"></div>
<div id = "b"></div>
<div id = "c"></div>
</div>
<script>
var a = [document.getElementById('a'),document.getElementById('b'),document.getElementById('c')];
var b = [document.getElementById('d').getElementsByTagName('div')];
</script>
複製程式碼
問a 和 b 的區別
我們把結果列印出來看一下:
a
b
看MDN官方對Element.getElementsByTagName()
這個說法的解釋:
“Element.getElementsByTagName()
方法返回一個動態的包含所有指定標籤名的元素的HTML集合HTMLCollection
。指定的元素的子樹會被搜尋,不包括元素自己。返回的列表是動態的,這意味著它會隨著DOM樹的變化自動更新自身。所以,使用相同元素和相同引數時,沒有必要多次的呼叫Element.getElementsByTagName()
.”
很多人(包括我和作者)都會以為這題差別是在b返回的是二維陣列,其實都是想當然了。
a返回的是一個包含三個dom元素的陣列,而b返回的是隻有一個HTMLCollection
元素的陣列。這是完全的兩種結構且HTMLCollection
並不繼承自Array
.
- 1、
HTMLCollection
是及時更新的,當文件中的DOM變化時,它是會隨之變化的 - 2、
HTMLCollection
可以用HTMLCollection.item()
、HTMLCollection.namedItem()
這種方式來獲取內部元素。
題目二 陣列去重
請手打一個陣列去重的方法,題目是[1,2,3,2].distinct() = [1,2,3]。
複製程式碼
關於陣列去重的方法有很多,網上資料太多不再贅述,作者用的是一種hash去重的方法。
Array.prototype.distinct = Array.prototype.distinct || function(){
var len = this.length,
i = 0,
hash = {},
myArr = [];
for(; i < len; i ++){
if(!hash[this[i]]){
hash[this[i]] = true;
myArr.push(this[i])
}
}
return myArr;
}
複製程式碼
這種方法可以達到題目中的要求,但並不是一種嚴謹的陣列去重方式。
假設我們的的陣列變成[1,2,3,2,'1']
,這種方法就無法達到去重的效果了,這種方式無法區分數字1和字串'1',還需要通過型別判斷。
關於陣列去重,最簡單的是ES6的:
Array.prototype.distinct = Array.prototype.distinct||function(){
console.log(this);
return Array.from(new Set(this)); //return [...(new Set(this))];
}
複製程式碼
題目三,考察閉包
function mo(){
var x = 0;
return function(){
console.log(++x)
}
}
var a = mo();
var b = mo();
a();
a();
b();
複製程式碼
答案是1,2,1。
a 和 b是不同的兩個函式,分別保持著各自對不同的x的引用。
題目四
var p = [];
var A = new Function();
A.prototype = p;
var a = new A;
a.push(1);
console.log(a.length);
console.log(p.length);
複製程式碼
答案:1,0。
這題要理解的一點是:
a.__proto__ === p
複製程式碼
按照<<高階程式設計>>
中講解的new的過程:
- 建立一個新物件
- 將建構函式的作用域賦給新物件(因此this就指向了這個新物件)
- 執行建構函式中的程式碼(為這個物件新增屬性)
- 返回新物件
我們模仿一下new這個過程發生的事:
new A
=>
(funciton(){
//第一步,把__proto__指向p(A.prototype)
//第二步,按照p(A.prototype)的樣子創造一個物件(克隆)
var a = Object.create(A.protype);
A.call(a);
return a;
})()
複製程式碼
new 如果在繼承物件是沒有引數的情況下,是可以不加後面的括號的,編譯器會自動替你加上的。但是要記住new的沒有括號優先順序是低於.的,有括號是高於();
題目五,陣列降維
[1,2,3,[4,5,[6,7]]]
複製程式碼
下面是原文作者提供的兩種寫法:
function fn(arr){
var tempArr = Array.from(arr.join('-')); //join()會自動新增逗號
for(var i = 0;i<tempArr.length;i++){
if(isNaN(tempArr[i])){
tempArr.splice(i,1)
}
}
return tempArr;
}
複製程式碼
function fn(arr){
var myArr = [];
var fn2 = function(arr2){
for(var i = 0;i<arr2.length;i++){
if(Array.isArray(arr2[i])){
fn2.call(null,arr2[i])
}
else{
myArr.push(arr2[i]);
}
}
}
fn2(arr);
return myArr;
}
fn([1,2,3,[4,5,[6,7]]]);
複製程式碼
這裡再提供一種簡潔的寫法:
let flatten = arr => arr.reduce((pre,cur)=>{
Array.isArray(cur)?pre.push(...flatten(cur)):pre.push(cur);
return pre
},[])
複製程式碼
面試
函式宣告和函式表示式有什麼區別
答:解析器有一個函式宣告提升的過程,讀取並將函式宣告新增到執行環境中,Javascript在第一遍會宣告函式並將它們放到原始碼的頂部。使其在執行任何程式碼之前可用。
函式宣告既然會提升,優先順序是什麼,和var比呢
答:函式提升優先順序比變數提升要高,且不會被變數宣告覆蓋,但是會被變數賦值覆蓋,也會被後面的同名函式替換。
console.log(typeof(foo)); //function
function foo(){}
var foo = 5;
複製程式碼
foo = 5;
console.log(typeof(foo)); //number
function foo(){}
複製程式碼
函式宣告的提升為什麼會比var高,編譯器幹了什麼事情
引擎在執行javascript
程式碼之前,會先將其進行編譯,編譯階段會找到所有宣告,並找到合適的作用域將它們關聯起來。
Javascript在第一遍會宣告函式並將它們放到原始碼的頂部
函式宣告提升的是整個函式,變數宣告提升的僅僅是var a
;這部分。
函式宣告會將變數宣告覆蓋,而變數宣告只能當做重複宣告被忽略。所以函式宣告的提升比var高。(純個人理解,如有不對歡迎指出
)
es6 裝飾器用過沒,是幹什麼用的(應該是es7的,反正我也沒答出來,答出來肯定還繼續深的問)
裝飾類、裝飾方法或屬性。裝飾器可以聯想到裝飾器模式:向一個現有的物件新增新的功能,同時又不改變其結構的設計模式,它是作為現有的類的一個包裝。
es6中的擴充套件運算子...的實現原理
呼叫預設的iterator介面
<-------------------以下內容是原文作者的回答,明天接著刷,大家有好的答案之類非常歡迎提供---------------------------->
es6中的解構中的...和上面的區別
答:說真的,我也不知道啥區別,不是一樣用嗎?
[...org,name] = [1,2,3,4] 這樣的話,org裡是個啥
答:開始問的放後面是啥,我想了半天,沒敢說,我說難道後面的就沒抓到,全被org抓走了?其實不是,直接報錯了,...是rest的意思,既然是rest,那就只能放在最後啊
更新說明我還不會用,區別應該是問的es7中的解構。原理就是es6直接採用for of,也就是說,所有總有迭代器的物件都能使用擴充套件運算子,在es6裡說不能放前面的,但是在es7裡如果用於物件是可以放前面的。懂了這個,上面幾題就都該會了
for of 和for in區別
答:for in 是鍵值對形式,for of 是輸出value形式,然後for of只要是配置了迭代器,都能遍歷。
this的指向問題
答:這個正常的都說了
箭頭函式中的this
答:這裡說的不好,我只說了用了箭頭函式的話,this就被傳進來了。就不需要繫結進來了。
箭頭函式中的this預設指向在定義它時,它所處的物件,而不是執行時的物件, 定義它的時候,可能環境是window
什麼是閉包(這裡答的不太好,雖然都會用啊處理的,我用類似如下程式碼舉例,貌似面試官並不滿意...)
function aa(){
var a = 1;
return function bb(){
console.log(a);
}
}
aa()()
複製程式碼
什麼是作用域
答:在進入指令碼標籤編譯階段的時候就定義了各類作用域,外面的變數就在全域性作用域,函式內部的就在函式的作用域裡,作用域外的函式不能訪問某個作用域裡面的東西
什麼是作用域鏈
答:在各級執行上下文建立階段的時候,就確定了各級作用域,串起來就是作用域鏈了。比如閉包的時候外部函式出棧之後,內部函式還保留了對外部函式某個變數的引用,就是通過作用域鏈找過去的
什麼是原型
答:prototype,好像我也說不出啥,就舉個函式的寫原型的例子。 js有哪些設計模式(我說有工廠模式,建構函式模式,原型模式,面試官說這是物件導向,不過我覺得有啥區別,物件導向程式設計不久是要用這些設計模式嗎) 這些模式都是咋寫的,我手寫給他看
為什麼要用原型
答:共享原型裡的東西給下屬繼承的物件,這樣在new的時候不用重新建立,節省記憶體空間
eval的缺點
答:我說了用法,就是可執行string,然後缺點沒說,沒怎麼研究,只是看了一眼用法型別的
with的缺點
答:沒用過,在網上看到過,說不要用,然後我就不用,應該會導致效能問題吧
在嚴格模式下能不能用eval
答:不能
es5和es6嚴格模式的區別
答:不知道
什麼是柯里化,舉React和Redux的例子
答:解釋了柯里化是啥,舉不出來例子,沒看過原始碼啊或者是對react瞭解的不夠多
什麼是純函式
答:不產生任何互動的函式?答的不好,我說reducer應該就是個純函式,猜對了而已。
純函式是指 不依賴於且不改變它作用域之外的變數狀態 的函式純函式的概念連結
頁面和伺服器之間的互動有哪幾種(ajax,websocket,不滿意)
ajax的Type有幾種(我只知道post和get)
這題我可能沒有理解... get和post的區別(我說的表象區別,url引數,安全性,大小限制,面試官不是很滿意)
與 POST 相比,GET 更簡單也更快,並且在大部分情況下都能用。 然而,在以下情況中,請使用 POST 請求: 無法使用快取檔案(更新伺服器上的檔案或資料庫) 向伺服器傳送大量資料(POST 沒有資料量限制) 傳送包含未知字元的使用者輸入時,POST 比 GET 更穩定也更可靠
HTTP請求頭上都有什麼資訊
答:UA,HOST,其他的我也沒說,就說還有幾個沒注意..
如何統計頁面上的按鈕被點選了多少次
答:和伺服器互動?反正也只能存伺服器啊...
單頁面應用和多頁面應用的區別
答:一個跳頁面是內部的,一個跳頁面是href整頁重新整理的。
哪種更容易被SEO到,優化SEO
答:猜測是多頁面,頁面多唄...優化的不知道
上兩題補充連結
cookie和localstorage區別(我說大小,安全,有效期,貌似又不是很滿意)
JSON.stringify(大OBJ)的時候會有什麼問題 答:效能損失。
script標籤順序怎麼控制,涉及到依賴必須要有先後
答:在HTML層就控制順序唄,顯然不是他要的答案
除了直接引用script標籤,如果不用import require這樣的東西,怎麼呼叫其它頁面的js
答:真不知道,a.js裡除了用script標籤引用b.js
import和require的區別
答:import是靜態載入,一旦你import,內容就進來了,require是動態載入,用的時候才載入,後面又問了一些,後面就不會了
函式節流怎麼實現
答:簡單是settimeout,時間超出就執行,沒超出再進來的話就直接clear掉。面試官覺得太簡單了。
canvas 繪製原理
答:不知道
如何使用canvas拖動一個小球撞擊另外一個小球,然後另外一個小球被撞擊出去 答:canvas一年半沒用鐵定不記得了(總共也就2年經驗),但是說了一下實現思路
canvas 裡有很多小球時如何優化效能
答:不知道
微信小程式跳轉頁面最多能跳轉多少層 不會
RN中listview 的key值的實現原理 不會
然後還問了一些關於專案上的問題,以及如何設計一個搜尋元件,需要考慮到哪些問題。 應該就這些,沒想起來的想起來再補充,感覺答的不好,很多都不記得了。 三分之一的題目 比如實現原理啊,缺點啊,為什麼啊,會有什麼問題啊,此類問題要麼不會,要麼答的不好 總共就這麼多,我要繼續鞏固基礎了~!!!!!!!
金三銀四,看見大家都在為了面試而努力 特開了一個前端模擬面試題,組織了面試的群友每天來群裡分享面試題,講題 急思眾議,共同進步,歡迎最近在面試或者準備面試的群友加入本群,加群格式: 工作年限-面試等級(初、中、高)-工作地點 (不在面試或者不準備面試或者不活躍的勿加本群,加了也會被清理)