幾個讓我印象深入的面試題(二)

前言

原文地址&&個人博客
知乎&&知乎專欄
簡書
河南前端交流羣官網javascript

上次寫了一篇幾個讓我印象深入的面試題(一)沒看過的同窗能夠去看哦。
此次文章的題目來源:這裏有超過20家的前端面試題,你肯定不點進來看看?
若是上面的問題在我這篇文章裏沒有提到的話,那就說明有些問題能夠很容易查獲得或者很簡單或者我能力有限不能解答出來的。若是有的問題你不會並且我又沒有提的那就認爲就是我能力有限不能解答出來吧。嘿嘿嘿。開個玩笑,不過能夠在下面留言哦!html

正文

仍是老規矩先給題目,而後在看個人答案,有什麼意見能夠在留言板提。前端

  1. 請問a,b,c分別輸出什麼?java

function fun(n,o){
    console.log(o)
    return{
      fun:function(m){
         return fun(m,n);
      }
    };
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1); c.fun(2); c.fun(3);
  1. 用盡量多的方法找出數組中重複出現過的元素git

例如:[1,2,4,4,3,3,1,5,3]es6

輸出:[1,3,4]github

  1. 給定一些文檔(docs)、詞(words),找出詞在文檔中所有存在的全部文檔面試

var docs = [{
        id: 1,
        words: ['hello',"world"]
    },
    {
        id: 2,
        words: ['hello',"kids"]
    },
    {
        id: 3,
        words: ['zzzz',"hello"]
    },
    {
        id: 4,
        words: ['world',"kids"]
    }
 ];
findDocList(docs,['hello']) //文檔1,文檔2,文檔3
findDocList(docs,['hello','world']) //文檔1
  1. 下面代碼會輸出什麼?ajax

var test = (function(a){
    this.a = a;
    return function(b){
        return this.a + b;
    }
    }(function(a,b){
        return a;
    }(1,2)));
console.log(test(1));
  1. 不用循環,建立一個長度爲 100 的數組,而且每一個元素的值等於它的下標。正則表達式

  2. 一個整數,它的各位數字若是是左右對稱的,則這個數字是對稱數。那麼請找出 1 至 10000 中全部的對稱數

  3. 如下代碼輸出結果是什麼?

var myObject = {
    foo: "bar",
    func: function(){
         var self = this;
         console.log('outer func : this.foo' + this.foo);
         console.log('outer func : self.foo' + self.foo);
         (function(){
             console.log('inner func : this.foo' + this.foo);
             console.log('inner func : self.foo' + self.foo);
         })();
    }
};
myObject.func();
  1. 請寫出如下正則表達式的詳細規則說明
    /^(0[1-9]dd?)?[1-9]d{6}d?$/

/^(1[89]|[2-9]d|100)$/i
/^[w-]+@[a-z0-9-]+({[a-z]{2,6}}){1,2}$/i

  1. 請寫出打亂數組方法

  2. 寫出element.getElementsByClassName 的實現方法

  3. 請寫出代碼輸出結果

if(!("a" in window)){
    var a = 1;
}
alert(a);
  1. 請寫出代碼輸出結果

var handle = function(a){
    var b = 3;
    var tmp = function(a){
        b = a + b;
        return tmp;
    }
    tmp.toString = function(){
        return b;
    }
    return tmp;
}
alert(handle(4)(5)(6));
  1. javscript表達式"[]==''"的值是什麼,爲何?

  2. Js生成下面html,點擊每一個li的時候彈出1,2,3......
    //li onclick事件都能彈出當前被點擊的index=?

<ul id="testUrl">
    <li>index=0</li>
    <li>index=1</li>
</ul>
  1. map方法是ES5中新增的,要求爲ES5如下的環境增長個map方法

答案揭曉

第一題

function fun(n,o){
   console.log(o)
   return{
       fun:function(m){
           return fun(m,n);
       }
   };
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1); c.fun(2); c.fun(3);

咱們先來一步一步地看。首先是a=fun(0)由於只傳了一個參數,console輸出的是第二個參數的值,因此毫無疑問地輸出undefined

而後到a.fun(1)能夠看出,這句話是調用前面fun(0)返回回來的一個對象裏面的函數fun,這個fun又把fun(m,n)返回出去。這個時候請注意:這個對象裏的fun在返回以前調用了一下fun(m,n),因此console又會被執行,能夠肯定,它確定不會輸出傳進去的1,由於1做爲第一個參數傳到fun(m,n)裏,而console是輸出第二個參數的。那麼此次會輸出啥呢?

好了,不給你們賣關子了,答案是0。可能有人會問了,納尼?爲毛是0,0是哪來的?

要想看明白個人解釋,前提是你得清楚閉包。這裏用到了閉包。咱們知道,閉包有個功能就是外部做用域能經過閉包訪問函數內部的變量。其實在運行a=fun(0)的時候,return出來的對象裏的函數fun把傳進來的這個0做爲第二個參數傳到fun裏面並返回出來這時0獲得了保存。因此當運行a.fun(1)的時候其實輸出的是以前的0。後面的那兩個調用也和這個的原理同樣,最後都是輸出0。

這裏可能會有點繞,須要花點時間來看或者自行去調試。(我已經在盡力表達清楚了,若是還不懂的話就留言吧=.=)。

而後到b,若是前面搞懂了這裏就不難了。fun(0)運行的時候會return一個對象出去,後面的一串鏈式調用都是在調用前面函數返回的對象裏的fun,最終致使輸出是undefined 0 1 2

最後到c,若是b都搞懂了,到這裏基本就沒什麼難度了。分別會輸出undefined 0 1 1

若是還不懂的話建議單步調試一下,若是仍是不懂能夠在下面留言,我會盡最大能力給你解釋。

第二題

用盡量多的方法找出數組中重複出現過的元素
例如:[1,2,4,4,3,3,1,5,3]
輸出:[1,3,4]

個人思路是,先建立一個數組。而後將傳進來的數組進行排序。而後再利用sort方法遍歷數組,由於它能一次取到兩個數而後ab比較若是相等並且result裏面又沒有重複的就把a推動去。

這是個人代碼:

4.5日更新

感謝@倔強的小瓶蓋同窗指出的問題

function repeat(arr) {
    var result = [];
    arr.sort().reduce(function(a, b) {
        if(a === b && result.indexOf(a) === -1) {
            result.push(a);
        }
        return b;
    });
    return result;
}
//以前問題代碼
function repeat(arr){
    var result=[];
    arr.sort().sort(function(a,b){
        if(a===b&&result.indexOf(a)===-1){
            result.push(a);
        }
    });
    return result;
}

3.23日更新

感謝@start-wrap同窗提供的方法:

function repeat(arr){
    var result = [], map = {};
    arr.map(function(num){
    if(map[num] === 1) result.push(num);
        map[num] = (map[num] || 0) + 1;
    }); 
    return result;
}

值得一提的是map[num] = (map[num] || 0) + 1,這句代碼的(map[num] || 0)若是map[num]存在,則map[num]+1反之則0+1,我的以爲用得很巧妙。

感謝@早乙女瑞穂提供的淫技巧:

// es6
let array = [1, 1, 2, 3, 3, 3, 4, 4, 5];
Array.from(new Set(array.filter((x, i, self) => self.indexOf(x) !== i)));
// es5
var array = [1, 2, 4, 4, 3, 3, 1, 5, 3];
array.filter(function(x, i, self) {
    return self.indexOf(x) === i && self.lastIndexOf(x) !== i 
});

es6思路解說:

array.filter((x, i, self) => self.indexOf(x) !== i)
返回一個數組,該數組由arrary中重複的元素構成(返回N-1次)

new Set( [iterable] )
返回一個集合(重複元素在此被合併)

Array.from( [iterable] )
返回一個數組(將上一步的集合變爲數組)

//es5思路解說:

使用indexOflastIndexOf正向判斷和反向判斷這個元素是否是同一個數(若是是同一個數,則兩個方法返回的i是同樣的)

第三題

給定一些文檔(docs)、詞(words),找出詞在文檔中所有存在的全部文檔

個人思路是:把第二個參數的數組用join合成一個字符串,而後用forEach遍歷,分別把文檔裏的words也用join合成一個字符串,利用search方法找每一個文檔裏的words是否包含有arrStr

這是個人代碼:

function findDocList(docs, arr) {
    let arrStr = arr.join(""),
    itemStr,
    result = [];
    docs.forEach(function(item) {
        itemStr = item.words.join("");
        if(itemStr.search(new RegExp(arrStr)) !== -1) {
        result.push("文檔" + item.id);
    }
    });
    console.log(result);
}
findDocList(docs, ['hello']) //文檔1,文檔2,文檔3
findDocList(docs, ['hello', 'world']) //文檔1

第四題

下面代碼會輸出什麼?

var test = (function(a){
        this.a = a;
        return function(b){
        return this.a + b;
        }
}(function(a,b){
        return a;
}(1,2)));
console.log(test(1));

能夠看到,這裏有兩個自執行函數。下面這個自執行函數執行完後向上面這個自執行函數傳了個1因此this.a=1,這裏的this指向window。而後這個自執行函數返回個函數給test變量。下面調用test(1),這個1傳進來後至關於return 1+1因此就輸出2。

第五題

不用循環,建立一個長度爲 100 的數組,而且每一個元素的值等於它的下標。

若是瞭解Object.keysArray.form的話,這題基本上沒啥難度。
答案:

Object.keys(Array.from({length:100}))

哎!等下Array.form不是es6的嗎,es5的怎麼實現?
代碼來了:

Object.keys(Array.apply(null,{length:100}))

若是還不懂能夠參考這裏的講解。

第六題

一個整數,它的各位數字若是是左右對稱的,則這個數字是對稱數。那麼請找出 1 至 10000 中全部的對稱數

個人思路,先將數字轉爲字符串,而後利用數組的map方法遍歷這個字符串,將字符串所有分開變爲數組,而後調用數組的reverse方法,再將翻轉後的數組join成字符串,最後對比翻轉後的字符串和翻轉前的字符串是否相等便可(方法有點愚笨,望大神指教):

function symmetric(){
    var i=1,
    str,
    newStr,
    result=[];
    for(;i<1000;i++){
        str=""+i;
        newStr=result.map.call(str,function(item){
            return item;
        }).reverse().join("");
        if(str===newStr){
            result.push(+str);
        }
    }
    return result;
}

第七題

如下代碼輸出什麼?

var myObject = {
    foo: "bar",
    func: function(){
    var self = this;
    console.log('outer func : this.foo' + this.foo);
    console.log('outer func : self.foo' + self.foo);
    (function(){
        console.log('inner func : this.foo' + this.foo);
        console.log('inner func : self.foo' + self.foo);
    })();
    }
};
myObject.func();

這題主要考察this指向,我的以爲難度不是太大,由於this已經被我徹底承包啦(壞笑臉)。
這題的話只需考慮誰調用的函數this就指向誰。
函數開始執行self=this這裏的this是指向myObject的,由於myObject.func()很明顯是myObject在調用它嘛,因此頭兩句console輸出的foo都是bar
下面是一個自執行函數,要知道,自執行函數的this通常狀況下都指向window這裏也不例外,因此,第三個console輸出的fooundefined由於在windowfoo沒定義。第四個輸出的是self.foo這個self就是上面定義的selfmyObject因此,這裏的foobar

第八題

請寫出如下正則表達式的詳細規則說明
/^(0[1-9]dd?)?[1-9]d{6}d?$/
/^(1[89]|[2-9]d|100)$/i
/^[w-]+@[a-z0-9-]+({[a-z]{2,6}}){1,2}$/i

嘿嘿,正則也算我比較拿手的部分。我來一個一個解釋吧,有些正則比較難用語言表達,你們意會意會吧。

第一個:首先^表明的是以它後面的一堆東西爲開頭$表明以它前面一堆東西爲結尾,在這裏的意思就是以(0[1-9]\d\d?)?[1-9]\d{6}\d?爲開頭和結尾的字符串。而後到第一個括號裏的意思是匹配第一個字符串爲0第二個字符串爲1-9第三個字符串爲0-9第四個字符串無關緊要,有的話匹配1-9,而後這整個括號裏面的內容無關緊要。問好後面的意思是匹配第一個字符串是1-9而後後面6個字符串匹配0-9最後一個字符串無關緊要,有的話匹配0-9。

因此整理整理就是:匹配以0爲第一個,1-9爲第二個,數字爲第三個;第四個無關緊要,有的話匹配數字;而後前面這一整坨無關緊要。1-9爲第五個(若是前面那一坨沒有的話,則從第一個算起)而後後面6個都是數字最後一個數字無關緊要的字符串,且以它爲開頭和結尾。

下面是例子:
022222222222 //true
002222222222 //false 由於第二個數字是1-9
02222222222 //第一個括號最後一個數字者最後面的數字省略
0222222222 //第一個括號最後一個數字者最後面的數字省略
22222222 //第一個括號裏的內容所有省略
02222222 //d{6}沒有知足。

第二個:匹配以1做爲第一個,8或9做爲第二個又或者以2-9爲第一個,數字爲第二個又或者匹配100的字符串,並以他們爲開頭和結尾,忽略大小寫。

仍是例子比較直觀:

18 //true 匹配前面的1[89]
23 //true 匹配[2-9]d
100 //true 匹配100
17 //false
230 //false

第三個:
匹配前面至少一個數字或字母或_或-再匹配@而後再匹配至少一個字母或數字或-而後到再匹配{字母2-6個}1-2個,的字符串,並以他們爲開頭和結尾忽略大小寫。

這個用語言描述太難了,是我不會說話嗎,上例子吧:

3@d{aw}{ad} //true
-@-{ddd}{fs} //true
3@3{dw}{ddd} //true
3@3{dw} //false {字母2-6個}少了一個即({[a-z]{2,6}}){1,2}後面的{1,2}沒知足
@3{dw}{ddd} //false [w-]+沒知足
33{dw}{ddd} //false 沒@
dsa@ffff{dw}{d} //false ({[a-z]{2,6}})不符合

第九題

請寫出打亂數組方法

4.5日更新

參考這裏

// 以前的問題代碼
function randomsort(a, b) {
    return Math.random()>.5 ? -1 : 1;
    //用Math.random()函數生成0~1之間的隨機數與0.5比較,返回-1或1
}
var arr = [1, 2, 3, 4, 5];
arr.sort(randomsort);

第十題

寫出element.getElementsByClassName 的實現方法
個人思路:先獲取頁面下的全部元素,而後用split將傳進來的多個class分割成數組,而後利兩層循環找出符合條件的元素(我的以爲這種方法效率實在低下,就當是拋磚引玉吧,歡迎留言)
代碼:

if(!document.getElementsByClassName) {
    document.getElementsByClassName = function(className) {
    var ele = [],
        tags = document.getElementsByTagName("*");
    className = className.split(/\s+/);
    for(var i = 0; i < tags.length; i++) {
        for(var j = 0; j < className.length; j++) {
        //若是這個元素上有這個class且沒在ele裏面(主要防止多個class加在一個元素上推動去兩次的狀況)
            if(tags[i].className === className[j] && ele.indexOf(tags[i]) === -1) {
                ele.push(tags[i]);
            }
        }
    }
    return ele;
    }
}

第十一題

請寫出代碼輸出結果

if(!("a" in window)){
      var a = 1;
  }
  alert(a);

這題主要考察了變量的聲明提高,任何變量(es5中)的聲明都會提高到當前做用域的頂端。因此這裏的代碼其實爲:

var a;
  if(!("a" in window)){
      a = 1;
  }
  alert(a);

因此,在if語句執行前a就已經在window中了,因此這裏會atert undefined

第十二題

請寫出代碼輸出結果

var handle = function(a){
    var b = 3;
    var tmp = function(a){
        b = a + b;
        return tmp;
    }
    tmp.toString = function(){
        return b;
    }
    return tmp;
}
alert(handle(4)(5)(6));

咱們來一步一步看:首先是handle(4),到這裏,程序開始運行,建立了一個tmp函數,同時把tmp函數的toString方法重寫了,最後返回這個tmp函數。
注意tmp裏的a不是傳進去的4,不要把tmpahandlea搞混了,因此這裏傳的4啥也沒幹。

而後到第二步:handle(4)(5),這裏就是執行了tmp函數,這個時候tmp函數的a就是傳進來的5,·b就是第一步函數執行的b即3(不懂爲什麼是3的同窗再去了解了解閉包吧),最後這個b就等於8。

第三部重複第二步8+6,最後b爲14,javascript引擎最後自動調用了toString返回b,因此結果是14。

第十三題

javscript表達式"[]==''"的值是什麼,爲何?

這題考察對js==運算符的瞭解,咱們知道==運算符若是兩邊值類型不同會把它們轉換爲相同類型的值再來比較。這題左邊是object類型,右邊是string類型,因此會把左邊的轉化爲string類型來比較,[].toString()就是''因此最後結果是true

第十四題

Js生成下面html,點擊每一個li的時候彈出1,2,3......
//li onclick事件都能彈出當前被點擊的index=?

<ul id="testUrl">
    <li>index=0</li>
    <li>index=1</li>
</ul>

這題直接按照要求生成對應的html,再給ul綁定個事件,利用事件代理監聽是誰被點了,而後輸出它們的序號和對應的內容,沒啥難度。個人代碼:

var ul=document.createElement("ul"),
    lis=[];
    ul.id="testUrl";
for(var i=0,li;i<2;i++){
    li=document.createElement("li");
    li.innerHTML="index="+i;
    ul.appendChild(li);
    lis.push(li);
}
ul.addEventListener("click",function(e){
    alert(lis.indexOf(e.target));
    alert(e.target.innerHTML)
});
document.body.appendChild(ul);

第十五題

map方法是ES5中新增的,要求爲ES5如下的環境增長個map方法

我的認爲只要對map方法夠了解,天然就能封裝出來了。嘿嘿,不喜勿噴。給的連接雖然也有一個實現map的方法,可是用到了es5的for in不符合題目,因此個人代碼:

if(!Array.prototype.map){
    Array.prototype.map=function(callback,context){
    var len=this.length,
        i=0,
        result=[];
    if (typeof callback !== "function") {
        throw new TypeError(callback + " is not a function");
    }
    context=context||window;
    for(;i<len;i++){
        this[i]!==undefined?result.push(callback.call(context,this[i],i,this)):result.push(this[i]);
    }
    return result;
    }
}

不過個人代碼和標準的輸出結果仍是有點出入的。就是我不處理undefinednull,由於this[i]!==undefined,這兩個值是會原樣返回的。不過平常的一些需求仍是能知足的。歡迎你們提建議哈。

終於打完了,這期就這麼多題,但願能對你們有幫助,同時若是有不對的地方請及時指正,歡迎留言。

另外,歡迎你們來圍觀我封裝的一個ajax庫 lightings

參考

JS隨機打亂數組的方法小結
如何不使用loop循環,建立一個長度爲100的數組,而且每一個元素的值等於它的下標
MDN map

相關文章
相關標籤/搜索