JS里的数组

window.Array 和 window.Function

5 个 falsy 值: 0 NaN ‘’ undefined null
7 种数据结构: number string boolean null undefined symbol object(object 中函数和数组都是对象)

Array

js 中的 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象

  1. 当写 var a = Array(3) 时
    这个是执行 var a = Array(3) 后的内存图

  2. var a = Array(3, 3)
    这个时候就变成这样

  3. 加不加 new 对 Array 都一样

Function

Function 构造函数创建一个新的 Function 对象,在 js 中,每个函数实际上都是一个 Function 对象

var f = function(a, b) {
return a+b
}
// 等价于如下
var f = new Function('a', 'b', 'return a+b')

这里需要注意的是 function 是 js 的关键字,它可以用来声明一个函数,而 Function 则是 window 的一个对象

具名函数(有具体函数名称的函数)

function f(){
return undefined
}

匿名函数(没有名称的函数)

var f
f = function(){
}

什么是数组 & a.forEach

见下图

从上图中可以看到,本质上数组还是多了一个 Array.prototype 来指向最后的 Object.prototype,这个跟 obj 对象而言还是不一样的

有两种遍历方式

var obj = {
0:1, 1:2, 2:3, 3:4, length: 4;
}

for (let i=0; i < obj.length; i++) {
console.log(obj[i]);
} // 1 2 3 4
for (let i in obj) {
console.log(obj[i]);
} // 1 2 3 4(4会被打印两次,因为它只会遍历 obj hash)

伪数组

原型链中没有 Array.prototype 的叫伪数组(没有 push 和 pop 方法)

API

a = ['a', 'b', 'c', 'd']
a.forEach(function(x, y){
console.log('value', x);
console.log('key', y);
})

函数里面接受参数

function f(x, y) {
return x+y
}

函数里面接受一个函数

function f2(fn) {
console.log('我接收到了一个函数');
return undefined
}
f2 (function(){})

function x(y) {
if (typeof y !== 'function') {
console.log('滚');
return false;
} else {
console.log('我接收到了一个函数');
return true;
}
}
x(1) // 滚
x(function(){}) // 我接收到了一个函数

函数里面接受一个函数并执行

function x(y) {
if (typeof y !== 'function') {
console.log('滚');
return false;
} else {
console.log('我接收到了一个函数');
y()
console.log('并且我执行了这个函数')
return true;
}
}
x(function(){ console.log(2)})
// 我接收到了一个函数
// 2
// 并且我执行了这个函数

函数里面接受一个函数并执行同时传参给另一个函数

function x(y) {
if (typeof y !== 'function') {
console.log('滚');
return false;
} else {
console.log('我接收到了一个函数');
y(666)
console.log('并且我执行了这个函数')
return true;
}
}

x(function(xxx) {
console.log(xxx);
})
// 我接收到了一个函数
// 666
// 并且我执行了这个函数

所以 a.forEach 的流程就是

// array 是一个数组,而 f 是一个函数
function forEach(array, f) {
for (let i = 0; i < array.length; i++) {
// 执行这个函数
f(array[i], i)
}
}

forEach(['a', 'b', 'c'], function(value, key){
// 这个函数中就打印这句话
// 第一个参数一定是 value. 第二个参数一定是 key
console.log(value, key);
})

有一点需要注意的是,for 循环可以 break 和 continue;Array.prototype.forEach 不支持 break 和 continue

forEach 和 sort 的原理

forEach

a.forEach(function(){}) 之所以这里不传 a 的参数,是因为这里已经执行到了 a.forEach.call(a, function(){})

var obj = {0: 'a', 1: 'b', length:2};
// 这里调用到了 this
obj.forEach = function(x) {
for (let i = 0; i < this.length; i++) {
x(this[i], i);
}
};
obj.forEach(function(value, key){
console.log(value, key);
});

在传三个参数时,比如如下

a = ['fff', 'jjj', 'kkk'];
a.forEach(function(b, c, d) {
console.log(b, c, d);
})

// 结果是
fff 0
Array(3) [ "fff", "jjj", "kkk" ]
jjj 1
Array(3) [ "fff", "jjj", "kkk" ]
kkk 2
Array(3) [ "fff", "jjj", "kkk" ]

sort

sort 就是排序 api

a = [5, 6, 3, 4, 1, 2]
a.sort() // 1, 2, 3, 4, 5, 6
a.sort(function(x, y) {return x-y}); // 1, 2, 3, 4, 5, 6
a.sort(function(x, y) {return y-x}); // 6, 5, 4, 3, 2, 1
a = ['a', 'b', 'c']
hash = {
'a' : 2,
'b' : 1,
'c' : 3
}
a.sort(function(x, y) {return hash[x] - hash[y]})

join

在字符串中加入一段字符串

a = [1, 2, 3]
a.join('hello') // '1hello2hello3'
a.join(',') // '1, 2, 3'
a + '' // '1, 2, 3' 这个只是巧合

concat

用来连接字符串

var a = [1, 2, 3]
var b = [4, 5, 6]

var c = a.concat(b) // [1, 2, 3, 4, 5, 6]
var b = a.concat([]) // b => [1, 2, 3] 一般用来复制这个数组

map

map 就是把函数返回的值组成一个新数组,并返回

var a = [1, 2, 3]
// 与 forEach 差不多,只不过有个返回值
// a.forEach(function(){}) // undefined
a.map(function(value, key) {
return value * 2;
}) // [2, 4, 6]

// 上面的等价于箭头函数表示
a.map(value => value * 2) // [2, 4, 6]

fiter

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
a.filter(function(value, key) {
return value >= 5
}) // 5, 6, 7, 8, 9

// 链式操作
a.filter(function(value, key) {
return value >= 5
}).map(function(value) {
return value * value
}) // 25, 36, 49, 64, 81

reduce

遍历这个数组,每一次取一个结果,然后把这个结果放在下一项的身上

var a = [1, 2, 3]

a.reduce(function(sum, n){
return sum + n
}, 0) // 最后一个参数表示初始值

// 箭头函数表示
a.reduce((sum, n) => sum + n, 0)

最后一个例子

map 可以用 reduce 表示

a = [1, 2, 3]
a.reduce(function(arr, n) {
arr.push(n * 2)
return arr
}, [])

filter 可以用 reduce 表示

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a.reduce(function(arr, n){
if (n % 2 === 0) {
arr.push(n)
}
return arr
}, [])

总结

创造数组

  • Array()

其他类型转换成数组

全能

参考链接

Array MDN