[TOC]
# 题1、如何获取数组中元素的个数?
答: length
~~~
[1,2,2,3,4].length
~~~
# 题2、 shift、unshift、pop、push 四个方法是干什么用的
答:
shift:取出数组中的第 1 个元素,并且将这个元素从数组中删除。(弹出)
注意:通过下标 0 也可以获取数组中的第一个元素,arr\[0\],区别是这种不会删除第 1 个元素
unshift: 从数组的前面向数组中添加一个元素。
比如:\[1,2,3\].unshift(4) --> \[4,1,2,3\]
pop: 取出数组中最后一个元素,并且将这个元素从数组中删除。(弹出)
注意: 通过下标也可以获取数组中最后一个元素: arr\[arr.length-1\] ,区别是这种不会删除最后一个元素
push: 从数组的后面向数组中添加一个元素。
比如: \[1,2,3\].push(0) --> \[1,2,3,0\]
~~~
var arr = [1, 2, 2, 3, 4]
// 取出数组中的第 1 个元素,并且将这个元素从数组中删除
arr.shift();
console.log(arr); // [ 2, 2, 3, 4 ]
// unshift 从数组的前面向数组中添加一个元素
arr.unshift(0);
console.log(arr); // [ 0, 1, 2, 2, 3, 4 ]
// pop 取出数组中最后一个元素,并且将这个元素从数组中删除
arr.pop();
console.log(arr); // [ 1, 2, 2, 3 ]
// // push 往数组后面添加一个元素
arr.push(5);
console.log(arr); // [ 1, 2, 2, 3, 4, 5 ]
~~~
# 题3、如何创建一个拥有 10 个元素的数组?
答:let arr = new Array(10)
知识点复习:创建数组至少有两种方法:
~~~
let arr = new Array() // 创建空数组
let arr1 = [] // 创建空数组
~~~
# 题4、如何用数组模拟栈结构?
答: 栈 是一种数据结构,特点: 后进先出(LIFO: Last In First Out)。
![](http://ww1.sinaimg.cn/large/007WurYGgy1gf4zlwo39ej30e40a80uf.jpg)
可以使用 push 和 pop 实现入栈和出栈操作来模拟栈。
也可以使用 shift 和 unshift 实现入栈和出栈操作来模拟栈。
# 题5、如何用数组迷你队列结构?
答: 队列(queue)是一种数组,特点:先进先出(FIFO:Fist In First Out)。
![](http://ww1.sinaimg.cn/large/007WurYGgy1gf4zphwn6xj30k808iq4b.jpg)
可以使用 push 和 shift 方法实现入队和出队来模拟队列。 也可以使用 unshift 和 pop 方法实现入队和出队来模拟队列。
# 题6、如何获取数组中最后一个元素的值?
答:
方法一、下标 arr\[ arr.length - 1\] (只获取不会删除最后一个元素) 方法二、arr.pop() (获取并删除最后一个元素)
~~~
// 获取数组中最后一个元素的值
var arr = [1, 2, 2, 3, 4]
// 方法一、 arr[arr.length - 1] (只获取不会删除最后一个元素)
var a = arr[arr.length - 1]
console.log(a); // 4
// 方法二、pop() 方法 (获取并删除最后一个元素)
var b = arr.pop()
console.log(b); // 4
~~~
# 题7、如何把数组转成一个字符串?
答:
方法一、 join() 默认使用,隔开,也可以使用其他字符
方法二、toString() , 只能使用 , 隔开
~~~
// 把数组转成一个字符串
var arr = [1, 2, 2, 3, 4]
// 方法一、 join() 默认使用,隔开,也可以使用其他字符
var a = arr.join('')
console.log(a); // 1,2,2,3,4
// 方法二、toString() , 只能使用 , 隔开
var b = arr.toString()
console.log(b); // 1,2,2,3,4
~~~
# 题8、如何截取数组,比如:从数组中截取出第 2~4 个元素?
答:
方法一、splice() \[1,2,3,4,5,6,7,8\].splice(1, 5) 开始下标 ~ 截取长度 ,修改原数组 方法二、slice() , \[1,2,3,4,5,6,7,8\].slice(1, 5) , 开始下标 ~ 结束下标 ,不修改原数组
~~~
// 截取数组,比如:从数组中截取出第 2~5 个元素
var arr = [1, 2, 2, 3, 4, 5, 6, 7, 8, 9]
// 方法一、 splice() 开始的下标 - 截取长度,修改原数组
var a = arr.splice(1, 4)
console.log(a); // [ 2, 2, 3, 4 ]
console.log(arr); // [ 1, 5, 6, 7, 8, 9 ]
// 方法二、 slice() 开始的下标 - 结束下标,不修改原数组
var b = arr.slice(1, 5)
console.log(b); // [ 2, 2, 3, 4 ]
console.log(arr); // [ 1, 2, 2, 3, 4, 5, 6, 7, 8, 9 ]
~~~
# 题9、如何删除数组中的元素?
答: splice 。 比如: 删除第二个元素: arr.splice(1,1)
~~~
// 删除数组中的元素
var arr = [1, 2, 2, 3, 4]
arr.splice(1, 1)
console.log(arr); // [ 1, 2, 3, 4 ]
~~~
# 题10、如何对数组进行排序?
答:sort。 sort 可以用来对数组进行排序,但是使用时要注意:默认是 `按字符串` 进行排序的!!
![](http://ww1.sinaimg.cn/large/007WurYGgy1gf50enkgx2j30wg098ajp.jpg)
如何才能 `按数字` 来进行排序? 答:添加一个回调函数做为参数,这个回调函数有两个参数。
![](http://ww1.sinaimg.cn/large/007WurYGgy1gf50eyzcd5j30ro0ds46k.jpg)
回调函数可以简写为箭头函数:
![](http://ww1.sinaimg.cn/large/007WurYGgy1gf50f4gazsj30f8074wh3.jpg)
~~~
// 对数组进行排序
// 使用 sort()
var arr = [9, 23, 12, 123, 4, 8, 9, 10, 1, 7, 64, 34]
// 升序
arr.sort(function (a, b) { return a - b }) // [ 1, 4, 7, 8, 9, 9, 10, 12, 23, 34, 64, 123 ]
// 降序
arr.sort(function (a, b) { return b - a }) // [ 123, 64, 34, 23, 12, 10, 9, 9, 8, 7, 4, 1 ]
// 简写为箭头函数
arr.sort((a, b) => a - b) // [ 1, 4, 7, 8, 9, 9, 10, 12, 23, 34, 64, 123 ]
console.log(arr);
~~~
# 题11、什么是按引用传值?哪些遍历是按引用传值?
答:把一个变量在内存中的地址(引用)传过去。
对象类型(包含数组) 的数据都是按引用传值的。
![](http://ww1.sinaimg.cn/large/007WurYGgy1gf50sue1rxj30l60e6adr.jpg)
特点: a和b现在操作的是内存中的同一个数组。
比如:
![](http://ww1.sinaimg.cn/large/007WurYGgy1gf50ttgy3sj30w00bowp7.jpg)
总结:
1. 对象和数组在传值是按引用传值的。(传完之后,多个变量名操作的是同一个值)
2. 其他类型(数字、字符串、布尔等)不是按引用传值,其他类型是复制一份然后传值,(传完之后,彼此互不影响,各操作各的)
# 题12、引用的扩展面试题1?
请说出以下代码的输出结果 代码一、
~~~
let a = "abc"
let b = a // 不是引用传值,把 a 复制一份传给 b ,b 和 a 是两个独立的变量
b = 'hello' // b 和 a 是两个独立的变量,修改 b 不影响 a
console.log(a) // 输出 abc
console.log(b) // 输出 hello
~~~
代码二、
~~~
let a = [1,2,3]
let b = a // 数组是按引用传值,把 a 在内存中的地址传给 b ,a 和 b 指向同一个数组
b[1] = 100 // 修改 b 中的值, a 也会改变,因为 a 和 b 指向同一个数组
console.log(a) // 输出 [1,100,3]
console.log(b) // 输出 [1,100,3]
~~~
代码三、
~~~
let a = {name:'tom',age:10}
let b = a // 对象是引用传值,把 a 在内存中的地址传给 b ,a 和 b 指向同一个对象
b.age++ // 修改 b 对象就是修改 a 对象
console.log(a.age) // 输出 11
console.log(b.age) // 输出 11
~~~
# 题13、引用的扩展面试题2?
说出以下代码的输出结果: 代码一、
~~~
let a = 'abc'
function toUp(a) {
a = a.toUpperCase() // 这里的 a 和函数外面的 a 没有任何关系
}
toUp(a) // 不是按引用传递(按值传递),把 a 的值复制一份传到函数中,函数中的变量和 a 完全没有关系
console.log(a) // 输出 abc
~~~
代码二、
~~~
let a = [1,2,3]
function toUp(a) {
a[0] = 100 // 这个a 就是外面的 a ,所以修改这个,就是修改外面的 a
}
toUp(a) // 数组和对象都是按引用传递的,也就是说,函数中的 a 和外面的 a 是同一个 a
console.log(a) // 输出 [100,2,3]
~~~
上面两段代码函数参数中的 a 会给同学生造成误解,以为是同一个 a,其实 函数参数名是任意的, 代码一、
~~~
let a = 'abc'
function toUp(x) {
x = x.toUpperCase() // 这里的 a 和函数外面的 a 没有任何关系
}
toUp(a) // 不是按引用传递(按值传递),把 a 的值复制一份传到函数中,函数中的变量和 a 完全没有关系
console.log(a) // 输出 abc
~~~
代码二、
~~~
let a = [1,2,3]
function toUp(x) {
x[0] = 100 // 这个a 就是外面的 a ,所以修改这个,就是修改外面的 a
}
toUp(a) // 数组和对象都是按引用传递的,也就是说,函数中的 a 和外面的 a 是同一个 a
console.log(a) // 输出 [100,2,3]
~~~
当然还有一种情况:这个情况和引用没有关系,`变量作用域` 的问题:
~~~
let a = 'abc'
function toUp() {
a = a.toUpperCase() // 这个 a 就是外面的 a
}
toUp()
console.log(a) // 输出 ABC
~~~
# 题14、数组是按引用传递的,无法直接复制,那么应该如何复制(克隆)出一个新数组?
答: 方法一、(ES6)可以使用 ES6 中展开(...)运算符。(一维好使)
~~~
let a = [1,2,3,4]
let b = [...a] // 把 a 中的元素展开,赋给 b (复制了一份),a 和 b 是两个独立 的数组
b[0] = 100 // 不影响 a
console.log(a) // [1,2,3,4]
console.log(b) // [100,2,3,4]
~~~
方法二、先转字符串再转回数组( **几维都好使**)
~~~
let a = [1,2,3,4]
let b = JSON.parse(JSON.stringify(a)) // 复制克隆一份
b[0] = 100
console.log(a)
console.log(b)
~~~
方法三、slice(一维好使)
~~~
let a = [1,2,3,4]
let b = a.slice()
~~~
方法四、assign(ES6)(一维好使)
~~~
let a = [1,2,3,4]
let b = []
Object.assign(b,a) // 把 a 的值克隆一份给b
~~~
# 题15、如何合并两个数组?
答: 方法一、concat
~~~
let a = [1,2,3]
let b = [3,4,5]
let c = a.concat(b)
~~~
方法二、... (ES6)
~~~
let a = [1,2,3]
let b = [3,4,5]
let c = [...a, ...b]
~~~
# 题16、请说出至少 10 个操作数组的方法?
答:
concat: 合并数组
join: 转字符串
map: 循环并修改数组中的每个元素
filter: 过滤数组
find: 从数组中一个元素
findIndex: 从数组中查找一个元素的下标
sort: 排序
push: 从数组的后面添加元素
pop: 从数组的后面“弹出”元素
shift:从数组的前面添加元素
unshift: 从数组的前面“弹出”元素
slice: 截取数组(不删除)
splice: 截取数组的元素并删除
reverse: 反转数组元素的顺序
toString: 转成字符串
toLocaleString:转字符串
forEach: 循环数组中的元素
every(判断都满足):循环对数组中每个元素执行一个条件判断,如果所有的判断都返回 true ,那么最终结果是 true ,只要有一个是 false ,结果就是 false some(判断至少有一个满足):和 every 相反,只要数组中有一个满足条件就返回 true,如果全都不满足条件就返回 false
~~~
// some 和 every 和对比
let a = [3, 4, 5, 6, 7]
// 含义:every(每一个都满足):是否每一个都大于4
a.every(v => v > 4) // false
// 含义:some(有至少一个满足):是否有至少一个大于4
a.some(v => v > 4) // true
~~~
reduce:循环处理数组中所有的元素,最后可以把每个结果累加到一起,返回最终结果。要会使用这个函数,首先要明确参数的函数。
~~~
let a = [1, 2, 3, 4, 5]
// 参数一x、上一次计算的结果
// 参数二y、循环数组时的当前元素
// 参数三z、当前元素的下标
// 返回值:这一次的计算结果,这个结果会被当作下一次循环的累加结果(第一个参数)
// 比较数组中求和:
// 说明: return x+y 含义:上一次的累加结果(x) + 当前值,和做为下一次的累加结果
a.reduce(function (x, y, z) { return x + y })
// 简写:
a.reduce((a, b) => a + b) // 15
~~~
# 题17、有一个数组:\['abc','bcd','cd'\],如何将数组中每个元素的第 1 个字母变大写?
答:
~~~
let a = ['abc','bcd','cd']
// 1. 向字符串对象的原型中添加一个方法,这样所有字符串就可以直接使用这个方法了
String.prototype.ucfirst = function() {
// 转数组
let arr = this.split("") // ['a','b','c']
// 每1个元素大写
arr[0] = arr[0].toUpperCase() // ['A','b','c']
// 转字符
return arr.join("") // 'Abc'
}
// 2.对数组中每个字符串都执行 ucFirst 方法
a = a.map(v=>v.ucfirst())
console.log(a) // ['Abc','Bcd','Cd']
~~~