面试-----数组

1.如何判断一个变量是否为数组?

为什么不用typeof?

Array继承与Object,所以typeof 会直接返回object,所以不可以用typeof方法来检测

为什么不用instanceof?

var list = [1,2,3];
list instanceof Array    //true

instanceof 表面上看确实是返回了true,但其实并不可靠。原因是Array实质是一个引用,用instanceof方法(包括下面的constructor方法)都是利用和引用地址进行比较的方法来确定的但是在frame嵌套的情况下,每一个Array的引用地址都是不同的,比较起来结果也是不确定的,所以这种方法有其局限性

为什么不用constructor方法?

var list = [1,2,3];
list.constructor === Array;    //true

原因已经解释过了,不再赘述。

可靠的检测数组方式

1.利用Object的toString方法 ,Object.prototype.toString.call()方法

var list = [1,2,3];
Object.prototype.toString.call(list);    //[object Array]

2.利用ES6的Array.isArray()方法

var list = [1,2,3];
Array.isArray(list);    //true

2.数组的原生方法有哪些?

可以用MDN中给出的方式来回答:

会改变自身的方法

copyWithin、fill、pop、push、reverse、shift、sort、splice、unshift

 

不会改变自身的方法:

 

concat、includes、join、slice、toSource、toString、indexOf、lastIndexOf

 

遍历方法:

 

forEach、entries、every、some、filter、find、findIndex、keys、map、reduce、reduceRight、values

copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,而不修改其大小。

arr.copyWithin(target[, start[, end]])

参数 target
0 为基底的索引,复制序列到该位置。如果是负数,target 将从末尾开始计算。 如果 target 大于等于 arr.length,将会不发生拷贝。如果 target 在 start 之后,复制的序列将被修改以符合 arr.length。 start 0 为基底的索引,开始复制元素的起始位置。如果是负数,start 将从末尾开始计算。 如果 start 被忽略,copyWithin 将会从0开始复制。 end 0 为基底的索引,开始复制元素的结束位置。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。如果是负数, end 将从末尾开始计算。 如果 end 被忽略,copyWithin 将会复制到 arr.length。
返回值 改变了的数组。

fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。

arr.fill(value[, start[, end]])

参数
  value
      用来填充数组元素的值。
   start 可选
       起始索引,默认值为0。
   end 可选
       终止索引,默认值为 this.length。

返回值
    修改后的数组。

pop()方法从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。

语法
   arr.pop()
返回值
   从数组中删除的元素(当数组为空时返回undefined)。

push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。

语法
  arr.push(element1, ..., elementN)

参数
  elementN
   被添加到数组末尾的元素。

返回值
   当调用该方法时,新的 length 属性值将被返回。

reverse() 方法将数组中元素的位置颠倒,并返回该数组。该方法会改变原数组。

语法
 arr.reverse()
参数
 无

描述
   reverse 方法颠倒数组中元素的位置,并返回该数组的引用。

shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。

语法
   arr.shift()
返回值 
   从数组中删除的元素; 如果数组为空则返回undefined 。 

描述
   shift 方法移除索引为 0 的元素(即第一个元素),并返回被移除的元 
   素,其他元素的索引值随之减 1。如果 length 属性的值为 0 (长度 
   为 0),则返回 undefined。

   shift 方法并不局限于数组:这个方法能够通过 call 或 apply 方法作 
   用于类似数组的对象上。但是对于没有 length 属性(从0开始的一 
  系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何 
  意义。

unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度。

语法
     arr.unshift(element1, ..., elementN)
参数列表
    elementN
    要添加到数组开头的元素。
返回值
    当一个对象调用该方法时,返回其 length 属性值。

sort() 方法用原地算法对数组的元素进行排序,并返回数组。排序算法现在是稳定的。默认排序顺序是根据字符串Unicode码点。

3.说一说ES6对于数组有哪些扩展?

增加了扩展运算符(spread)...

它将一个数组转化为以逗号分隔的一个参数序列。

增加了两个方法,Array.from()和Array.of()方法。

 

增加了一些实例方法,如copyWithin()、find()和findIndex()、fill()entries()、keys()、values()、includes()等。

4.数组去重,你知道哪些方法?

1.利用一个空Object来实现

Array.prototype.unique = function(){
    var tmp = {},res=[];
    this.forEach(function(i){
        !tmp[i] && res.push(i) && (tmp[i] = true);
    })
    return res;
}
var list = [0,0,1,2,3,6,6];
console.log(list.unique());    //[0,1,2,3,6]

2.利用ES6 的Set数据结构

console.log([...new Set(list)]);    //[0,1,2,3,6]

5.你知道Array.prototype的类型是什么?

其实Array.prototype是一个数组,只不过length为0

6.如何“打平”一个嵌套数组,如[1,[2,[3]],4,[5]] => [1,2,3,4,5]?你知道多少方法?

这个方法很多,如果你的答案是用递归的话,那确实有点low,而且代码会比较复杂。

我的觉得可以用以下方法来解决这个问题:

1.利用Array.prototype.toString()方法

var list = [1,[2,[3]],4,[5]];
console.log(list.toString());    //1,2,3,4,5

原理:toString 方法返回一个字符串,该字符串由数组中的每个元素的 toString() 返回值经调用 join() 方法连接(由逗号隔开)组成。

2.利用Array.prototype.join()方法

var list = [1,[2,[3]],4,[5]];
console.log(list.join());    //1,2,3,4,5

原理:join方法会让所有的数组元素转换成字符串,再用一个分隔符将这些字符串连接起来。如果元素是undefined 或者null, 则会转化成空字符串。

PS:如果你觉得上面输出的不是一个数组,可以稍微加工一下

var list = [1,2,3,4,5];
JSON.parse(`[${list.toString()}]`);     //[1,2,3,4,5]
JSON.parse(`[${list.join()}]`);     //[1,2,3,4,5]

7.如何克隆一个数组?你能说出多少种?

1.借用concat方法
var arr1 = [1,2,3];
var arr2 = arr1.concat();
2.借用slice方法
var arr1 = [1,2,3];
var arr2 = arr1.slice(0);
原理:数组本质上也是Object,直接赋值的话,只是将引用赋值给另一个变量,最终会导致被复制的变量也会随着原来的数组变化而变化。

8.说一说Array.prototype.sort()方法的原理?(追问:不传递参数会如何?)

语法
sort方法接受一个“比较函数”作为参数。

如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。

如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
若 a 等于 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。

9.找出Array中最大的元素,你能说出几种方法?

1.自己实现一个冒泡算法,实现就不多说了
2.利用Math的max方法
var list = [1,100,23,65,43,2,9];
Math.max.apply(null, list);    //[1, 2, 9, 23, 43, 65, 100]
3.利用Array的sort方法先排序再取值
var list = [1,100,23,65,43,2,9];
list.sort((a, b) => {return a-b;})    //[1, 2, 9, 23, 43, 65, 100]

10.如何将一个类数组转化为数组?

(所谓类似数组本质特征就是必须有length属性)

1.ES5          Array.prototype.slice.call()的方法

       如果不确定环境的话,可以用Array.prototype.slice.call()的方法,将类似数组转换为数组。

2.ES6,       Array.from()方法。

  Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。

3.扩展运算符 ...

     扩展运算符可以将某些数据结构转换为数组,前提是该对象部署了遍历器接口(Symbol.iterator)

原文地址:https://www.cnblogs.com/shengnan-2017/p/10515320.html