在簡書看到這篇面試題,結合做者的答案和我的的理解作了一下,因我的水平有限(不謙虛,確實很菜),若是我的作的有什麼不對的歡迎指出來,共同交流javascript
做者:詩和元芳 連接: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 的區別java
咱們把結果打印出來看一下:react
a
es6
b
web
看MDN官方對Element.getElementsByTagName()
這個說法的解釋: 「Element.getElementsByTagName()
方法返回一個動態的包含全部指定標籤名的元素的HTML集合HTMLCollection
。指定的元素的子樹會被搜索,不包括元素本身。返回的列表是動態的,這意味着它會隨着DOM樹的變化自動更新自身。因此,使用相同元素和相同參數時,沒有必要屢次的調用Element.getElementsByTagName()
.」面試
不少人(包括我和做者)都會覺得這題差異是在b返回的是二維數組,其實都是想固然了。 a返回的是一個包含三個dom元素的數組,而b返回的是隻有一個HTMLCollection
元素的數組。這是徹底的兩種結構且HTMLCollection
並不繼承自Array
.ajax
HTMLCollection
是及時更新的,當文檔中的DOM變化時,它是會隨之變化的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的過程:
咱們模仿一下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在第一遍會聲明函數並將它們放到源代碼的頂部。使其在執行任何代碼以前可用。
答:函數提高優先級比變量提高要高,且不會被變量聲明覆蓋,可是會被變量賦值覆蓋,也會被後面的同名函數替換。
console.log(typeof(foo)); //function
function foo(){}
var foo = 5;
複製代碼
foo = 5;
console.log(typeof(foo)); //number
function foo(){}
複製代碼
引擎在執行javascript
代碼以前,會先將其進行編譯,編譯階段會找到全部聲明,並找到合適的做用域將它們關聯起來。 Javascript在第一遍會聲明函數並將它們放到源代碼的頂部 函數聲明提高的是整個函數,變量聲明提高的僅僅是var a
;這部分。
函數聲明會將變量聲明覆蓋,而變量聲明只能當作重複聲明被忽略。因此函數聲明的提高比var高。(純我的理解,若有不對歡迎指出
)
裝飾類、裝飾方法或屬性。裝飾器能夠聯想到裝飾器模式:向一個現有的對象添加新的功能,同時又不改變其結構的設計模式,它是做爲現有的類的一個包裝。
調用默認的iterator接口
<-------------------如下內容是原文做者的回答,明天接着刷,你們有好的答案之類很是歡迎提供---------------------------->
答:說真的,我也不知道啥區別,不是同樣用嗎?
答:開始問的放後面是啥,我想了半天,沒敢說,我說難道後面的就沒抓到,全被org抓走了?其實不是,直接報錯了,...是rest的意思,既然是rest,那就只能放在最後啊
更新說明我還不會用,區別應該是問的es7中的解構。原理就是es6直接採用for of,也就是說,全部總有迭代器的對象都能使用擴展運算符,在es6裏說不能放前面的,可是在es7裏若是用於對象是能夠放前面的。懂了這個,上面幾題就都該會了
答:for in 是鍵值對形式,for of 是輸出value形式,而後for of只要是配置了迭代器,都能遍歷。
答:這個正常的都說了
答:這裏說的很差,我只說了用了箭頭函數的話,this就被傳進來了。就不須要綁定進來了。
箭頭函數中的this默認指向在定義它時,它所處的對象,而不是執行時的對象, 定義它的時候,可能環境是window
function aa(){
var a = 1;
return function bb(){
console.log(a);
}
}
aa()()
複製代碼
答:在進入腳本標籤編譯階段的時候就定義了各種做用域,外面的變量就在全局做用域,函數內部的就在函數的做用域裏,做用域外的函數不能訪問某個做用域裏面的東西
答:在各級執行上下文建立階段的時候,就肯定了各級做用域,串起來就是做用域鏈了。好比閉包的時候外部函數出棧以後,內部函數還保留了對外部函數某個變量的引用,就是經過做用域鏈找過去的
答:prototype,好像我也說不出啥,就舉個函數的寫原型的例子。 js有哪些設計模式(我說有工廠模式,構造函數模式,原型模式,面試官說這是面向對象,不過我以爲有啥區別,面向對象編程不久是要用這些設計模式嗎) 這些模式都是咋寫的,我手寫給他看
答:共享原型裏的東西給下屬繼承的對象,這樣在new的時候不用從新建立,節省內存空間
答:我說了用法,就是可執行string,而後缺點沒說,沒怎麼研究,只是看了一眼用法類型的
答:沒用過,在網上看到過,說不要用,而後我就不用,應該會致使性能問題吧
答:不能
答:不知道
答:解釋了柯里化是啥,舉不出來例子,沒看過源碼啊或者是對react瞭解的不夠多
答:不產生任何交互的函數?答的很差,我說reducer應該就是個純函數,猜對了而已。
純函數是指 不依賴於且不改變它做用域以外的變量狀態 的函數純函數的概念連接
頁面和服務器之間的交互有哪幾種(ajax,websocket,不滿意)
這題我可能沒有理解... get和post的區別(我說的表象區別,url參數,安全性,大小限制,面試官不是很滿意)
與 POST 相比,GET 更簡單也更快,而且在大部分狀況下都能用。 然而,在如下狀況中,請使用 POST 請求: 沒法使用緩存文件(更新服務器上的文件或數據庫) 向服務器發送大量數據(POST 沒有數據量限制) 發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠
答:UA,HOST,其餘的我也沒說,就說還有幾個沒注意..
答:和服務器交互?反正也只能存服務器啊...
答:一個跳頁面是內部的,一個跳頁面是href整頁刷新的。
答:猜想是多頁面,頁面多唄...優化的不知道
上兩題補充連接
cookie和localstorage區別(我說大小,安全,有效期,貌似又不是很滿意)
JSON.stringify(大OBJ)的時候會有什麼問題 答:性能損失。
答:在HTML層就控制順序唄,顯然不是他要的答案
答:真不知道,a.js裏除了用script標籤引用b.js
答:import是靜態加載,一旦你import,內容就進來了,require是動態加載,用的時候才加載,後面又問了一些,後面就不會了
答:簡單是settimeout,時間超出就執行,沒超出再進來的話就直接clear掉。面試官以爲太簡單了。
答:不知道
如何使用canvas拖動一個小球撞擊另一個小球,而後另一個小球被撞擊出去 答:canvas一年半沒用鐵定不記得了(總共也就2年經驗),可是說了一下實現思路
答:不知道
RN中listview 的key值的實現原理 不會
而後還問了一些關於項目上的問題,以及如何設計一個搜索組件,須要考慮到哪些問題。 應該就這些,沒想起來的想起來再補充,感受答的很差,不少都不記得了。 三分之一的題目 好比實現原理啊,缺點啊,爲何啊,會有什麼問題啊,此類問題要麼不會,要麼答的很差 總共就這麼多,我要繼續鞏固基礎了~!!!!!!!
金三銀四,看見你們都在爲了面試而努力 特開了一個前端模擬面試題,組織了面試的羣友天天來羣裏分享面試題,講題 急思衆議,共同進步,歡迎最近在面試或者準備面試的羣友加入本羣,加羣格式: 工做年限-面試等級(初、中、高)-工做地點 (不在面試或者不許備面試或者不活躍的勿加本羣,加了也會被清理)