開頭,首先談一談前幾天去 攜程 的面試吧,剛開始筆試的題目,坦白說都是比較簡單的,開始大概是十道選擇題,都是基礎的理論題,通常基礎還能夠的人確定都會寫!接下來是幾道程序的運行題,主要考一些變量提高,閉包形式的運行結果,this指向問題,隨便舉幾個例子吧:面試
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, 我就是這麼理解的,因此很少作解釋啦....數組
var bb = 5;
function aa(bb) {
bb = 10;
alert(bb);
}
aa(bb);
alert (bb);
輸出的結果分別就是 10 和 5;
複製代碼
剛開始其實我考慮了一下,函數執行輸出結果在函數內部改變,因此輸出爲10 確定沒問題,其實不少人在這個地方考慮的是函數內部的值改變,會不會將外部的值也改變,參考一下函數變量的做用域,你就會發現其實並無改變!因此alert 的仍是 bb = 5;promise
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
Array.from(new Set());
可是這種方法通常面試官都不會買帳的,而後我想了另一種方法去實現,以下:
複製代碼
例如:閉包
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
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() 的具體機制和個人第二種方法有啥區別,就很尷尬了;異步
剛開始說這個的時候,其實我不懂啥意思,而後試探性的問了一下,是否是就是降維,可能腦海深處忽然蹦出來這個思惟邏輯吧,但並無啥卵用,我這個大菜鳥大概都忘了這些東西了,哈哈。。。而後隨便寫了幾行代碼,一團糟呢,如今想起來。下面給幾個思路:函數
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....這就是我想到的最簡單的辦法啦。。。嘿嘿!-->
複製代碼
第一種: 雙重 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
在攜程得這段面試,除了這些,還有一些較爲原理得原型鏈啊,閉包啥的,比較底層得知識,顯而易見得就是涼涼了啊.... 感受攜程常年招人,也不缺人呢!
var arr = [22,1,12,45,36]; arr.sort(function(a, b){ return a - b; }) // 默認爲升序;相反得若是return b - a; 就是相反得降序;
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();
})
複製代碼
//請求某個圖片資源
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);
});
複製代碼