最近遇到的問題總結(數組去重、扁平化處理、sort 以及Promise等等)

開頭,首先談一談前幾天去 攜程 的面試吧,剛開始筆試的題目,坦白說都是比較簡單的,開始大概是十道選擇題,都是基礎的理論題,通常基礎還能夠的人確定都會寫!接下來是幾道程序的運行題,主要考一些變量提高,閉包形式的運行結果,this指向問題,隨便舉幾個例子吧:面試

1. 首先說的這個題目其實至關經典的,不少地方都遇到過:

function Foo() {
    var i = 0;
    retunr function() {
        console.log(i++);
    }
}
var f1 = Foo(), f2 = Foo();
f1(); f1(); f2();
複製代碼

其實這一題感受就是考慮變量提高吧,輸出結果依此就是 0 1 0;簡單來講就是,第一次執行f1() 函數後,函數內部的 i 值就發生了改變,下一次執行f1(), i在原來的基礎上作了++ , 因此就輸出了 1,當執行f2函數的時候,從新執行了一次函數,因此輸出仍是原來的0, 我就是這麼理解的,因此很少作解釋啦....數組

2. 函數內部的變量問題:

var bb = 5;
function aa(bb) {
    bb = 10;
    alert(bb);
}
aa(bb);
alert (bb);
輸出的結果分別就是 10 和 5;
複製代碼

剛開始其實我考慮了一下,函數執行輸出結果在函數內部改變,因此輸出爲10 確定沒問題,其實不少人在這個地方考慮的是函數內部的值改變,會不會將外部的值也改變,參考一下函數變量的做用域,你就會發現其實並無改變!因此alert 的仍是 bb = 5;promise

3. 記憶中還考了一個obj 中的 this 指向問題,也很經典其實!簡單寫一個相似的吧:

var name =  'john';
var obj = {
    name: 'Bob',
    prop:{
        name: 'joyjoy',
        getName:function() {
            return this.name;
        }
    }
}
console.log(obj.prop.getName());         // joyjoy
var test = obj.prop.getName;
console.log(test());           //   john;
複製代碼

其實,對this 指向去研究過的童鞋,應該很好理解這個問題,第一次去直接訪問obj.prop.getName,那麼做用域很顯然就是在obj.prop 這個對象中,那麼確定會直接訪問這個對象中的name,因此打印的是joyjoy; 當實例化一個新的function的時候,test只表明對象中的一個函數,因此執行的時候會直接去需找所定義的name這個變量,因此確定是全局變量john 了;bash

二輪的時候,我一臉懵逼的去了,他們的CTO吧應該是,寫了一堆原生的問題,如下面兩個常常碰見的舉例:

一. 數組去重:

1.首先最簡單的寫法:

Array.from(new Set()); 
    可是這種方法通常面試官都不會買帳的,而後我想了另一種方法去實現,以下:
複製代碼

2. 新建一個對象,去判斷:

例如:閉包

let arr = [1,2,3,4,'4',5,5,6];
let obj = {};
let newArr = [];
for(let i = 0;i<arr.length;i++) {
    if(!obj[arr[i]]) {
        newArr.push(arr[i]);
        obj[arr[i]] = true;
    }
}
// 輸出的newArr 爲 [1,2,3,4,5,6]
複製代碼

經過鍵值對的形式,也能夠實現這個問題,當時面試官質疑了我這種方法,說萬一裏面number類型,字符串類型都存在,會被默認去重,就像上述數組中的 4 和 '4' 同樣;回來想一想確實是的,再仔細想了想,仍是不知道咋解決,因而便再從新想了一個方法: (ps: 下面這個想法,高度緊張,卡住了,由於他依舊沒有解決這個問題啊);app

3.雙重for 循環去實現:

var arr=[1,2,3,4,4,4,5,5,5,5,5,6];
var resultArr = [];
for(var i = 0;i< arr.length;i++) {
	for(var j = i+1;j<arr.length;j++) {
		if(arr[i] == arr[j]) {
			j = ++i;
		}
	}
	resultArr.push(arr[i]);
}
// 輸出 [1,2,3,4,5,6]
複製代碼

這個方法內部判斷條件,其實能夠換成splice 在 原數組上直接修改的,具體的就不介紹啦;dom

想了不少,好像就只有 new Set() 能夠區分上面的數值和字符串問題,但我又不瞭解new Set() 的具體機制和個人第二種方法有啥區別,就很尷尬了;異步

二: 數組的扁平化處理

剛開始說這個的時候,其實我不懂啥意思,而後試探性的問了一下,是否是就是降維,可能腦海深處忽然蹦出來這個思惟邏輯吧,但並無啥卵用,我這個大菜鳥大概都忘了這些東西了,哈哈。。。而後隨便寫了幾行代碼,一團糟呢,如今想起來。下面給幾個思路:函數

1. 回來想到最簡單的方法,用arr.join() 方法去實現這玩意兒;

var arr = [1,2,3,4,[5,6],[7,8,]];
var newArr = Array.from(arr.join());
for (var i = 0;i<newArr.length;i++) {
	if(isNaN(newArr[i])){
		newArr.splice(i,1);
	} 
}
<!--emmm....這就是我想到的最簡單的辦法啦。。。嘿嘿!-->
複製代碼

2. 其實可能面試官更想要的就是網上的那循規蹈矩的三種方法吧: 簡單提一下吧

第一種: 雙重 for 循環: 
var result = [];
for(var i=0;i<arr.length;i++){
    for(var j=0;j<arr[i].length;j++){
        result.push(arr[i][j]);
    }
}

第二種: 用concat代替內層循環
var result = [];
for(var i=0;i<arr.length;i++){
    result = result.concat(arr[i]);
}

第三種:用apply代替外層遍歷
var result = [].concat.apply([],arr);

複製代碼

固然了,上面這三個方法就初步實現了簡單的二維數組降維,多重數組降維,還須要經過遞歸的方法去實現的:

一個簡單的實現思路:

var arr = [2, 3, [2, 2],
    [3, 'f', ['w', 3]], { "name": 'Tom' }
];
let result = [];
arr.forEach(function(val, index) {
    if(Array.isArray(val)) {
        val.forEach(arguments.callee);
    } else {
        result.push(val);
    }
})
console.log(result);   // 這個就解決了多重數組得降維了....
複製代碼

ps: 稍微解釋一下 arguments.callee, 首先顯而易見得就是 callee 就是arguments 中得一個屬性,他是一個指針, 指向擁有arguments 這個對象得函數,經常使用於遞歸函數,不過如今通常不使用啦!!!!ui

在攜程得這段面試,除了這些,還有一些較爲原理得原型鏈啊,閉包啥的,比較底層得知識,顯而易見得就是涼涼了啊.... 感受攜程常年招人,也不缺人呢!

再說一些別的地方遇到得面試題吧,首先數組和字符串得一大堆用法,就不一一細說了,最想說得就是 sort 排序得功能了:

一: sort 排序:

1. 首先,sort() 方法會對數組元素進行排序,並返回這個數組;可是sort() 在默認不傳比較函數的時候,會將數組中得全部元素經過toString() 方法 轉化,在進行字符串比較,因此在默認對數字數組進行排序的時候,會出現問題,因此引入了比較函數:

var arr = [22,1,12,45,36]; arr.sort(function(a, b){ return a - b; }) // 默認爲升序;相反得若是return b - a; 就是相反得降序;

2.數組得多條件排序,實例以下:
var array = [{id:10,age:2},{id:5,age:4},{id:6,age:10},{id:9,age:6},{id:2,age:8},{id:10,age:9}]; array.sort(function(a,b){
    if(a.id === b.id){
        return b.age - a.age  // 若是id的值相等,按照age的值降序 
    }else{ 
        return a.id - b.id  // 若是id的值不相等,按照id的值升序
    }   
    }) 
    輸出結果:
    [{"id":2,"age":8},{"id":5,"age":4},{"id":6,"age":10},{"id":9,"age":6},{"id":10,"age":9},{"id":10,"age":2}]

##### 3. sort 實現亂序(這個方法不太好,就隨口提一下): 
    Array.sort(function(){
        return 0.5 - Math.random();
    })

複製代碼

二: 在簡單的說一下 Promise 操做吧,反正去哪都會被問到.....

promise這個 構造函數 簡單的 resolve 、 reject 以及 .all 和 .catch 這幾個方法就不詳細說了額,寫一個簡單得demo 去實現圖片得資源加載吧...

ps: 首先咱們都知道 .all 和 .race 的區別就 .all 就是判斷哪個異步函數執行得慢,就以哪個函數爲準去執行回調, 而.race 偏偏相反, 誰執行得快,就以哪個函數爲準執行回調!因此咱們就能夠寫兩個函數分別去實現加載圖片和顯示延時,具體代碼以下:
//請求某個圖片資源
    function requestImg(){
        var p = new Promise(function(resolve, reject){
            var img = new Image();
            img.onload = function(){
                resolve(img);
            }
            img.src = 'xxxxxx';
        });
        return p;
    }
    //延時函數,用於給請求計時
    function timeout(){
        var p = new Promise(function(resolve, reject){
            setTimeout(function(){
                reject('圖片請求超時');
            }, 5000);
        });
        return p;
    }
    
    Promise
    .race([requestImg(), timeout()])
    .then(function(results){
        console.log(results);
    })
    .catch(function(reason){
        console.log(reason);
    });
    
複製代碼

遇到得問題還有不少不少啊... 在這條求坑之路中摸索前行,其實蠻難的,加油吧!!!但願有大神指點額......

相關文章
相關標籤/搜索