JS数组

Get Started

• 数组对象
• 增删改查

数组对象

一种特殊的对象
JS其实没有真正的数组,只是用对象模拟数组

JS的数组不是典型的数组

• 典型的数组
元素的数据类型相同
使用连续的内存存储
通过数字下标获取元素
• 但JS 的数组不这样
元素的数据类型可以不同
内存不一定连续(对象是随机存储的)
不能通过数字下标,而是通过字符串下标
这意味着数组可以有任何key
比如
let arr = [1, 2, 3]
arr['xxx'] = 1

创建一个数组

• 新建

    let arr = [1, 2, 3]
    let arr = new Array(1, 2, 3)
    let arr = new Array(3)

• 转化

    let arr = '1,2,3'.split(',')
    let arr = '123'.split('')
    Array.form('123')(有下标,有length)

• 伪数组:有着数组格式的对象
let divList = document.querySelector('div')
伪数组的原型链中并没有数组的原型
• 合并两个数组,返回一个新数组
arr1.concat(arr2)
• 截取一个数组的一部分,并返回(原数组不变)

    arr1.slics(1) //从第二个元素开始
    arr1.slice(0) //全部截取

注意:JS只提供浅拷贝
split() 方法用于把一个字符串分割成字符串数组
用法:stringObject.split(separator,howmany)
concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
用法:var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
用法:arr.slice([begin[, end]]) (包前不包后)

增删改查

数组中的元素

• 跟对象一样

    let arr = ['a', 'b', 'c']
    delete arr['0']
    arr //['empty', 'b', 'c']

• 注意数组的长度并没有变,叫做稀疏数组。
• 直接改length可以删元素

    let arr = [1, 2, 3, 4, 5];
    arr.length = 1

重要:不要随便改length

推荐

• 删除头部的元素
arr.shift()
shift()方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
• 删除尾部的元素
arr.pop()
pop()方法从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。
• 删除中间的元素

    arr.splice(index, 1)//删除index(下标)的一个元素
    arr.splice(index, 1, 'x')//···并在删除位置添加'x'
    arr.splice(index, 1, 'x', 'y')//···并在删除位置添加'x''y'

splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

查看所有元素

• 查看所有属性名

    let arr = [1, 2, 3, 4, 5]; arr.x = 'xxx'
    Object.keys(arr)//Object.values(arr)

• 适用于对象,返回由key或者value组成的数组。
for(let keyin arr){console.log(`${key}:${arr[key]}`)}
• 查看数字(字符串)属性名和值

    for ( let i = 0; I < arr.length; i++ ){
      console.log(`${key}:${arr[i]}`)
    }
    要自己让i从0增长到length-1(遍历)
    arr.forEach(function(item, index)){
      console.log(`${index}:${item}`)
    }
也可以用forEach/map等原型上的函数

• forEach() 方法对数组的每个元素执行一次给定的函数。被调用时,不会改变原数组。
arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
• arr.forEach(function(item, index, array))
数组中正在处理的当前元素,下标,正在操作的数组(放桃子的筐,顺序,一堆桃子)
thisArg可选参数。当执行回调函数 callback 时,用作 this 的值。
返回值:undefined
注意:forEach不支持break和continue
for循环时块级作用域,forEach是函数作用域
• 例一:将 for 循环转换为 forEach

    const items = ['item1', 'item2', 'item3'];
    const copy = [];
    // before
    for (let i=0; i<items.length; i++) {
      copy.push(items[i]);
    }
    // after
    items.forEach(function(item){
      copy.push(item);
    });

• 例二:打印出数组的内容

    function logArrayElements(element, index, array) {
      console.log('a[' + index + '] = ' + element);
    }
    // 注意索引 2 被跳过了,因为在数组的这个位置没有项
    [2, 5, , 9].forEach(logArrayElements);
    // logs:
    // a[0] = 2
    // a[1] = 5
    // a[3] = 9

• 例三:扁平化数组

    function flatten(arr) {
      const result = [];
      arr.forEach((i) => {
        if (Array.isArray(i)){
          console.log(i);
          result.push(...flatten(i));
        }else{
          result.push(i);
        }
      })
      return result;
    }
    // Usage
    const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]];
    flatten(problem);
    >>
    (5) [4, 5, Array(2), 8, 9]
    (2) [6, 7]
    (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]

查看单个属性
• 跟对象一样

    let arr = [111, 222, 333]
    arr[0]

• 索引越界

    arr[arr.length] === undefined
    arr[-1] === undefined

• 报错
Cannot read property 'toString' of indefined
意思是你读取了undefined的toString属性,x.toString()中x如果是undefined,就报这个错
• 查找某个元素是否在数组里
arr.indexOf(item) //存在返回索引,否则返回-1
• 使用条件查找元素
arr.find(item => item%2===0)
//查找第一个偶数
• 使用条件查找元素的索引
arr.findIndex(item => item%2===0)
//查找第一个偶数的索引

增加数组中的元素

• 在尾部加元素

    arr.push(newItem) //修改arr,返回新长度
    arr.push(item1, item2) //修改arr,返回新长度

• 在头部加元素

    arr.unshift(newItem) //修改arr,返回新长度
    arr.unshift(item1, item2) //修改arr,返回新长度

• 在中间添加元素

    arr.splice(index, 0, 'x') //在index处插入'x'
    arr.splice(index, 0, 'x', 'y')

修改数组中元素的顺序

• 反转顺序
arr.reverse() //修改原数组
• 自定义顺序
arr.sort((a, b) => a - b)

数组变换

map() 方法
创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
• n变n
• 语法
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
• 数组中正在处理的当前元素,下标,正在操作的数组(放桃子的筐,顺序,一堆桃子)
• 例子

    let arr = [0,1,2,2,3,3,3,4,4,4,4,6]
    let arr2 = arr.map((i) => {
      const date = {0:'周日', 1: '周一', 2: '周二',3: '周三', 4: '周四', 5: '周五', 6: '周六'}
      return date[i]
    })
    console.log(arr2) // ['周日', '周一', '周二', '周二', '周三', '周三', '周三', '周四', '周四', '周四', '周四','周六']

filter() 方法
创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
filter 不会改变原数组,它返回过滤后的新数组。
• n变少
• 语法
var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
• 例子

    let scores = [95,91,59,55,42,82,72,85,67,66,55,91]
    let scores2 = scores.filter(item => item/60 >= 1)
    console.log(scores2) //  [95,91,82,72,85,67,66, 91]

reduce() 方法
对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
• n变1
• 语法
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
• accumulator
累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue
• 例子

    let scores = [95,91,59,55,42,82,72,85,67,66,55,91]
    let sum = scores.reduce((sum, n)=>{
      return n%2===0?sum:sum+n
    },0)
    console.log(sum) // 奇数之和:598 

面试题

• 数据变换

    let arr = [
      {名称: '动物', id: 1, parent: null},
      {名称: '狗', id: 2, parent: null},
      {名称: '猫', id: 3, parent: null}
    ]
    数组变成对象
    {
      id: 1, 名称: '动物', children:[
        {id: 2, 名称: '狗', children: null},
        {id: 3, 名称: '猫', children: null}
      ]
    }

• 代码

    arr.reduce((result, item) => {
    if( item['名称'] === '动物' ) {
        result.id = item.id
        result['名称'] = item['名称']
      } else {
        result.children.push(item)
        delete item.parent
        item.chilred = null
      }
      return result
    },{id:null, children: []})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容