數(shù)組面試題

1、如何判斷數(shù)組是數(shù)組類型来庭?

  • Array.isArray() 最靠譜的判斷數(shù)組的方法

    在調(diào)用這個方法之前重寫了Object.prototype.toString方法或修改constructor對象稍味,不影響判斷的結(jié)果

    Object.prototype.toString = ()=>{
        console.log('Hello Howard');
    }
    const a = [];
    Array.isArray(a);//true
    
    a.constructor = b.constructor;
    Array.isArray(a);//true
    

    兼容寫法

    if (!Array.isArray) {
      Array.isArray = function(arg) {
        return Object.prototype.toString.call(arg) === '[object Array]';
      };
    }
    
  • 驗證構(gòu)造函數(shù)

    • instanceof判斷:判斷某個構(gòu)造函數(shù)的prototype屬性所指向的對象是否存在于要檢測對象的原型鏈上
    object instanceof constructor
    
    const a = [];
    const b = {};
    console.log(a instanceof Array);//true
    console.log(a instanceof Object);//true,在數(shù)組的原型鏈上也能找到
    Object構(gòu)造函數(shù)
    
    

    ? 驗證不夠嚴格删咱。 即使對象創(chuàng)建時不是使用數(shù)組創(chuàng)建的杖小,但是只要原型鏈上有數(shù)組類型

    function Test(){}
    Test.prototype = Array.prototype;
    let test = new Test();
    test instanceof Array;//true
    
    • constructor:實例化的數(shù)組擁有一個constructor屬性,這個屬性指向生成這個數(shù)組的方法

      obj.constructor == Array
      
      const a = [];
      console.log(a.constructor);//function Array(){ [native code] }
      
  • 驗證原型對象

    • getPrototypeOf: 這是Object自帶的一個API碾阁,作用是獲取一個對象的原型對象
      • Object.getPrototypeOf(obj) == Array.prototype
    • isPrototypeOf:每個對象都有一個isPrototypeOf的API输虱,繼承自O(shè)bject.prototype
      • var bool = Array.prototype.isPrototypeOf(obj)
  • 檢查內(nèi)部屬性class + call或apply

    每個對象中記錄對象創(chuàng)建時使用的類型的屬性,一旦對象被創(chuàng)建脂凶,class屬性就無法被修改宪睹。獲得class的唯一的辦法就是調(diào)用Object.prototype中的toString()方法

    const a = ['Hello','Howard'];
    Object.prototype.toString.call(a);//"[object Array]"
    Object.prototype.toString.apply(a);//"[object Array]"
    
    

2、數(shù)組與字符串

  • 由數(shù)組轉(zhuǎn)換為字符串蚕钦,使用join亭病;
  • 由字符串轉(zhuǎn)換為數(shù)組,使用split
// join - 由數(shù)組轉(zhuǎn)換為字符串嘶居,使用join
console.log(['Hello', 'World'].join(','));    // Hello,World
// split - 由字符串轉(zhuǎn)換為數(shù)組罪帖,使用split
console.log('Hello World'.split(' '));    // ["Hello", "World"] 

3、查找元素

indexOf : arr.indexOf(searchElement[, fromIndex])
searchElement:需檢索的元素
fromIndex:可選整數(shù)參數(shù)邮屁,規(guī)定在數(shù)組中開始檢索的位置

// indexOf - 查找元素
console.log(['abc', 'bcd', 'cde'].indexOf('bcd'));  // 1

4整袁、數(shù)組連接

使用concat之后會生成一個新的數(shù)組

var array1 = [1, 2, 3];
var array2 = [4, 5, 6];
var array3 = array1.concat(array2); // 實現(xiàn)數(shù)組連接之后,會創(chuàng)建出新的數(shù)組
console.log(array3);

5佑吝、類列表操作

push/pop/shift/unshift

var array = [2, 3, 4, 5]; // 添加到數(shù)組尾部
array.push(6);
console.log(array); // [2, 3, 4, 5, 6] 

// 添加到數(shù)組頭部
array.unshift(1);
console.log(array); // [1, 2, 3, 4, 5, 6] 

// 移除最后一個元素
var elementOfPop = array.pop();
console.log(elementOfPop); // 6
console.log(array); // [1, 2, 3, 4, 5] 

// 移除第一個元素
var elementOfShift = array.shift();
console.log(elementOfShift); // 1
console.log(array); // [2, 3, 4, 5] 

6坐昙、splice方法

主要兩個用途:

  • 從數(shù)組中間位置添加和刪除元素
  • 從原有數(shù)組中,獲取一個新數(shù)組

需提供如下參數(shù)

  • 起始索引(也就是你希望開始添加元素的地方)
  • 需要刪除的元素的個數(shù)或是提取的元素的個數(shù)(添加元素時該參數(shù)設(shè)置為0)
  • 想要添加進數(shù)組的元素
var nums = [1, 2, 3, 7, 8, 9];
nums.splice(3, 0, 4, 5, 6);
console.log(nums);  // [1, 2, 3, 4, 5, 6, 7, 8, 9] 
// 緊接著做刪除操作或者提取新的數(shù)組
var newnums = nums.splice(3, 4);
console.log(nums);  // [1, 2, 3, 8, 9]
console.log(newnums);   // [4, 5, 6, 7] 

7芋忿、排序

reverse:數(shù)組反轉(zhuǎn)

// 反轉(zhuǎn)數(shù)組
var array = [1, 2, 3, 4, 5];
array.reverse();
console.log(array); // [5, 4, 3, 2, 1]

sort:按照字典順序?qū)υ剡M行排序民珍,在調(diào)用方法時傳入一個大小比較函數(shù)襟士,排序時盗飒,sort()方法將會根據(jù)該函數(shù)比較數(shù)組中兩個元素的大小

var compare = function(num1, num2) {
    return num1 > num2;
};
nums.sort(compare);
console.log(nums);  // [1, 2, 3, 4, 100, 200] 

var objInArray = [
    {
        name: 'king',
        pass: '123',
        index: 2
    },
    {
        name: 'king1',
        pass: '234',
        index: 1
    }
];
// 對數(shù)組中的對象元素嚷量,根據(jù)index進行升序
var compare = function(o1, o2) {
    return o1.index > o2.index;
};
objInArray.sort(compare);
console.log(objInArray[0].index < objInArray[1].index); // true

8、for of, for in 和 forEach用法及其區(qū)別

  • for in:用于遍歷數(shù)組或者對象的屬性
    • 缺點:鍵名是字符串逆趣;會遍歷對象本身的所有可枚舉屬性和從它原型繼承而來的可枚舉屬性蝶溶,僅迭代對象本身的屬性,要結(jié)合hasOwnProperty()來使用宣渗;
let aArray = ['a',123,{a:'1',b:'2'}];
aArray.name = 'demo';
for(let index in aArray){
    console.log(index); //0,1,2,name也被循環(huán)出來了
}
var obj = {
    name:"echolun",
    age:"24",
    sex:"male"
},
objName=[], //用來裝對象屬性名
objVal=[];  //用來裝對象屬性值
Object.prototype.game="lastgame";
for(var i in obj){
    if(obj.hasOwnProperty(i)) {
        objName.push(i);
        objVal.push(obj[i]);
    }
}
console.log(objName,objVal);
}
  • for of:可迭代對象(Array抖所,Map,Set痕囱,String田轧,TypedArray,arguments)上創(chuàng)建一個迭代循環(huán)
for(var value of aArray){
    console.log(value); // 'a',123,{a:'1',b:'2'}
}
var student={
    name:'wujunchuan',
    age:22,
    locate:{
    country:'china',
    city:'xiamen',
    school:'XMUT'
    }
}
for(var key of Object.keys(student)){
    //使用Object.keys()方法獲取對象key的數(shù)組
    console.log(key+": "+student[key]);
}
  • for of 與 for in 區(qū)別
    • 推薦在循環(huán)對象屬性的時候鞍恢,使用for...in,在遍歷數(shù)組的時候的時候使用for...of傻粘。

    • for...in循環(huán)出的是key,for...of循環(huán)出的是value

    • for...of是ES6新引入的特性帮掉。修復了ES5引入的for...in的不足

    • for...of不能循環(huán)普通的對象弦悉,需要通過和Object.keys()搭配使用

  • forEach:用于遍歷數(shù)組,在運行途中無法跳出循環(huán)蟆炊,break和return不起作用稽莉,空數(shù)組無法執(zhí)行回調(diào)函數(shù)

9、數(shù)組去重

  • ES6 Set去重: 無法去掉“{}”空對象
var set = new Set([1, 2, 3, 3, 4]); //先把數(shù)組轉(zhuǎn)化為set集合
Array.from(set)  //輸出[1,2,3,4]  通過Array.from這個方法把集合在轉(zhuǎn)化為數(shù)組
[...new Set(arr)] //簡化寫法
  • 利用for嵌套for涩搓,然后splice去重(NaN和{}沒有去重)
function unique(arr){            
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){
                if(arr[i]===arr[j]){         //第一個等同于第二個污秆,splice方法刪除第二個
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}
var arr = [false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
//[false, undefined, null, NaN, NaN, "NaN", 0, "a", {}, {}]   NaN和{}沒有去重
  • 利用indexOf去重: 新建一個空的結(jié)果數(shù)組,for 循環(huán)原數(shù)組昧甘,判斷結(jié)果數(shù)組是否存在當前元素良拼,如果有相同的值則跳過,不相同則push進數(shù)組(NaN和{}沒有去重)
function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}
var arr = [false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
//[false, undefined, null, NaN, NaN, "NaN", 0, "a", {}, {}]   NaN和{}沒有去重
  • 利用sort(): 根據(jù)排序后的結(jié)果進行遍歷及相鄰元素比對(NaN和{}沒有去重)
function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return;
    }
    arr = arr.sort()
    var arrry= [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            arrry.push(arr[i]);
        }
    }
    return arrry;
}
     var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//(14) [0, 1, 15, NaN, NaN, "NaN", {}, {}, "a", false, null, "true", true, undefined]
  • 利用filter({}沒有去重)
function unique(arr) {
  return arr.filter(function(item, index, arr) {
    //當前元素疾层,在原始數(shù)組中的第一個索引==當前索引值将饺,否則返回當前元素
    return arr.indexOf(item, 0) === index;
  });
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {}, {}]
  • 利用hasOwnProperty (所有的都可以去重)
function removeDuplicates(arr){  
    var i, len=arr.length;  
    var array=[], obj={};  
    for(i=0; i<len; i++){  
        if(!obj.hasOwnProperty(arr[i])){  
            array.push(arr[i]);  
            obj[arr[i]] = true;  
        }  
    }  
    return array;  
} 
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
// [1, "true", 15, false, undefined, null, NaN, 0, "a", {}]
  • 利用includes:檢測數(shù)組是否有某個值({}沒有去重)
//和indexOf 去重方法類似,只是if()里改為!array.includes(arr[i])

10痛黎、數(shù)組隨機排序

  • 法一予弧、
    • 遍歷數(shù)組,每次循環(huán)都隨機一個在數(shù)組長度范圍內(nèi)的數(shù)湖饱,并交換本次循環(huán)的位置和隨機數(shù)位置上的元素
  • 法二掖蛤、
    • 申明一個新的空數(shù)組,利用while循環(huán),如果數(shù)組長度大于0井厌,就繼續(xù)循環(huán)蚓庭;
    • 每次循環(huán)都隨機一個在數(shù)組長度范圍內(nèi)的數(shù)致讥,將隨機數(shù)位置上的元素push到新數(shù)組里,
    • 并利用splice(對splice不太理解的同學可以看這里)截取出隨機數(shù)位置上的元素器赞,同時也修改了原始數(shù)組的長度垢袱;
  • 法三、利用傳入sort排序中的比較函數(shù)
    • 如果 compareFunction(a, b)的返回值 小于 0 港柜,那么 a 會被排列到 b 之前请契;
    • 如果 compareFunction(a, b)的返回值 等于 0 ,那么a 和 b 的相對位置不變夏醉;
    • 如果 compareFunction(a, b)的返回值 大于 0 爽锥,那么b 會被排列到 a 之前;
 function randomSort3(arr){
    arr.sort(function(a,b){
        return Math.random() - 0.5;
    });
    return arr;
}

11畔柔、JavaScript數(shù)組迭代(遍歷)方法

forEach: 對數(shù)組中每一項運行給定函數(shù)氯夷。該函數(shù)沒有返回值

var arr = [1, 2, 3];
var obj = {name: 'zhang'};

arr.forEach(function (element, index, array) {
  console.log(element, index, array, this)
}, obj)

// output
1 0 [1, 2, 3] {name: "zhang"}
2 1 [1, 2, 3] {name: "zhang"}
3 2 [1, 2, 3] {name: "zhang"}

以下方法有返回值(有返回值的方法,callback需要有return值)
map: 對數(shù)組中每一項運行給定函數(shù)靶擦。返回每次函數(shù)調(diào)用的結(jié)果組成的函數(shù)

var data = [1, 2, 3];

var arrayOfSquares = data.map(function (element) {
  return element * element;
});

console.log(arrayOfSquares); //[1, 4, 9]

filter: 對數(shù)組中的每一項運行給定函數(shù)腮考。返回該函數(shù)會返回 true 的項組成的數(shù)組

var arr = [0, 1, 2, 3];

var newArr = arr.filter(function (element, index, array) {
  return e;
})

var newArr2 = arr.filter(function (element, index, array) {
  return e>=2; 
})

console.log(newArr); // [1, 2, 3]
console.log(newArr2); // [2, 3]

some: 對數(shù)組中每一項運行給定函數(shù)。如果函數(shù)對 任一項返回 true奢啥,則返回 true

function isBigEnough(element, index, array) {
  return element >= 4;
}
var passed = [1, 2, 3].some(isBigEnough);
var passed2 = [1, 2, 3, 4].some(isBigEnough);

console.log(passed); // false
console.log(passed2); // true

every: 對數(shù)組中的每一項運行給定函數(shù)秸仙。如果函數(shù)對每一項都返回 true,則返回 true

function isBigEnough(element, index, array) {
  return element >= 3;
}
var passed = [2, 3, 4].every(isBigEnough);
var passed2 = [3, 4, 5].every(isBigEnough);

console.log(passed); // false
console.log(passed2); // true

find / findIndex: 用于找出第一個符合條件的數(shù)組成員返回undefined/-1

var value = [1, 5, 10, 15].find(function(element, index, array) {
  return element > 9;
});
var value2 = [1, 5, 10, 15].find(function(element, index, array) {
  return element > 20;
});

console.log(value); // 10
console.log(value2); // undefined

以上方法中的callback函數(shù)會被依次傳入三個參數(shù):
數(shù)組當前項的值
數(shù)組當前項的索引
數(shù)組對象本身
還可以傳入第二個可選參數(shù)桩盲,callback函數(shù)里的this將指向這個參數(shù)寂纪。默認this指向全局對象(在瀏覽器是為window),嚴格模式下是undefined

reduce / reduceRight: 讓數(shù)組中的前項和后項某種計算赌结,并累計最終值/從最后一個值開始計算的

var sum = [1, 2, 3].reduce(function(a, b) {
    return a + b;
});
console.log(sum); // 6

其中callback可以依次接受四個參數(shù):
accumulator上一次調(diào)用回調(diào)返回的值捞蛋,或者是提供的初始值(initialValue)
currentValue數(shù)組中正在處理的元素
currentIndex數(shù)組中正在處理的元素索引,如果提供了initialValue 柬姚,從0開始拟杉;否則從1開始。
array數(shù)組對象本身
reduce / reduceRight 方法中量承,第二個參數(shù)(initialValue)是可選的搬设;其值用于第一次調(diào)用callback的第一個參數(shù)。

var sum = [0,1,2,3,4].reduce(function(accumulator, currentValue, currentIndex, array){
  console.log(accumulator, currentValue, currentIndex, array)
  return accumulator + currentValue;
}, 10);
console.log(sum);

// output
10 0 0 [0, 1, 2, 3, 4]
10 1 1 [0, 1, 2, 3, 4]
11 2 2 [0, 1, 2, 3, 4]
13 3 3 [0, 1, 2, 3, 4]
16 4 4 [0, 1, 2, 3, 4]
20

參考文章:JavaScript數(shù)組迭代(遍歷)方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撕捍,一起剝皮案震驚了整個濱河市拿穴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌忧风,老刑警劉巖默色,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異狮腿,居然都是意外死亡腿宰,警方通過查閱死者的電腦和手機呕诉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吃度,“玉大人甩挫,你說我怎么就攤上這事」骐龋” “怎么了捶闸?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拖刃。 經(jīng)常有香客問我,道長贪绘,這世上最難降的妖魔是什么兑牡? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮税灌,結(jié)果婚禮上均函,老公的妹妹穿的比我還像新娘。我一直安慰自己菱涤,他們只是感情好苞也,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粘秆,像睡著了一般如迟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上攻走,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天殷勘,我揣著相機與錄音,去河邊找鬼昔搂。 笑死玲销,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的摘符。 我是一名探鬼主播贤斜,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼逛裤!你這毒婦竟也來了瘩绒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤别凹,失蹤者是張志新(化名)和其女友劉穎草讶,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炉菲,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡堕战,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年坤溃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘱丢。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡薪介,死狀恐怖殖演,靈堂內(nèi)的尸體忽然破棺而出刊侯,到底是詐尸還是另有隱情,我是刑警寧澤玖雁,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布缀旁,位于F島的核電站记劈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏并巍。R本人自食惡果不足惜目木,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望懊渡。 院中可真熱鬧刽射,春花似錦、人聲如沸剃执。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肾档。三九已至摹恰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阁最,已是汗流浹背戒祠。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留速种,地道東北人姜盈。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像配阵,于是被迫代替她去往敵國和親馏颂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容