引用数据类型

Posted love599

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了引用数据类型相关的知识,希望对你有一定的参考价值。

第五章 引用数据类型

本章指引

javascript 中,除了六种基本数据类型之外,就只有一种引用数据类型 —— 对象。

我们在本章将学习自己自定义对象,并且使用它们。除了使用自己自定义对象以外,JavaScript 语言中已经自带了很多对象,我们将其称之为“内置对象”,我们将在本章学习内置对象中的数组,SetMap

而在本章不管是数组、SetMap,还是对象,它们都表现出了一个共同的特征,可以按某种特定的结构存放大量的数据。这些数据存放在一起作为一个整体我们可以称它们是一个集合;而集合中数据间存在关系,这就说明数据就是有结构的,那么这个集合也可以叫做数据结构。

所谓数据结构,就是计算机存储和组织数据的方式。说得通俗一点,主要就是指将数据以什么样的结构存储到计算机里面。

在程序里面,最为常见的数据结构,就是数组,这种结构将多个数据有序的排列在一起,形成了一个集合。除了数组以外,SetMapECMAScript 6 (下面简称ES6)新增加的数据结构,也会在本章中向大家详细介绍。

本章主要包含以下内容:

  • 对象

  • 数组基础

  • 数组的常用方法

  • Set

  • Map

 

5-1 对象

JavaScript 中的对象(Object)是一组数据的无序集合。其中,每一条数据都是由键:值组成(例如:name:‘HanMeiMei‘ )。其中,值可以是任意数据类型,而键是字符串类型。

5-1-1 定义对象

定义对象的方式有两种:

  • 字面量方式:

    let obj1 = {};
  • 构造函数方式:

    let obj2 = new Object();

###5-1-2 对象的属性

当对象中某一条数据的键所对应的值是非函数类型,则我们将这条数据叫做对象的属性。

let student = {
name: ‘HanMeiMei‘,
age: 20
}

上面代码中,name 和 age 两个键对应的值都不是函数,因此这两条数据我们就叫做 student 对象的属性。

属性操作

  • 通过点运算符.来操作一个对象的属性。

    let person = {
    name: "lisi",
    job: "SoftWare Engineer"
    };
    person.name = "zhangsan";             // 修改已有的属性
    person.age = 30;                      // 添加没有的属性
    console.log( person.job );            // 查看已有的属性
    ?
    ?
  • 通过方括号[]操作一个对象的属性。

    let person = {
    name: "lisi",
    job: "SoftWare Engineer"
    };
    person["name"] = "zhangsan";             // 修改已有的属性
    person["age"] = 30;                      // 添加没有的属性
    console.log( person["job"] );            // 查看已有的属性
  • 通过 delete 关键字来删除一个对象的属性。

    let person = {
    name: "lisi",
    job: "SoftWare Engineer"
    };
    delete person.job;             // 删除 person 对象的属性 job

###5-1-3 对象的方法

当对象中某一条数据的键所对应的值是函数类型,则我们将这条数据叫做对象的方法。

let person = {
name: ‘HanMeiMei‘,
introduce: function(){
console.log( ‘my name is HanMeiMei‘ );
}
}

上面代码中,introduce 键对应的值都是一个函数,因此这条数据我们就叫做 student 对象的方法。

方法操作

对象方法的操作类似于对象属性的操作,同样具有以下三种方式:

  • 通过点运算符.来访问一个对象的方法。

    let person = {
    name: ‘HanMeiMei‘,
    introduce: function(){
    console.log( ‘my name is HanMeiMei‘ );
    }
    }
    person.introduce();    // 调用 person 对象的 introduce 方法
  • 通过方括号[]来访问一个对象的方法。

    let person = {
    name: ‘HanMeiMei‘,
    introduce: function(){
    console.log( ‘my name is HanMeiMei‘ );
    }
    }
    ?
    person["introduce"](); // 调用 person 对象的 introduce 方法
  • 通过 delete 关键字来删除一个对象的方法。

    let person = {
    name: ‘HanMeiMei‘,
    introduce: function(){
    console.log( ‘my name is HanMeiMei‘ );
    }
    }
    delete person.introduce;             // 方法名后面没有小括号

###5-1-4 对象的遍历

for-in

let name = Symbol(‘name‘);
let person = {
   name: ‘HanMeiMei‘,
   age: 20,
   gender: ‘male‘,
   introduce: function () {
       console.log(‘my name is HanMeiMei‘);
  }
}
?
for (let key in person) {
   console.log(key);    // name age gender introduce
}

for-in 可以遍历所有的属性和方法,要注意的是,for-in 无法遍历通过 symbol 值定义的属性。

###5-1-5 对象方法中的 this

对象的方法中可以使用 this 关键字。

let foo = { 
bar: function(){
console.log(this);
}
}
foo.bar();           // { bar: [Function: bar] }

对象方法中的 this 永远指向调用该方法时.或[]前的那个对象。如上例中 bar 方法的 this 就一定指向 foo 对象。

let student = {
name: ‘HanMeiMei‘,
sayName: function () {
console.log(‘my name is ‘ + this.name);
}
}
student.sayName();

###5-1-6 对象的扩展

对象的解构

var { name: name=99, age: age } = { name: "zhangsan", age: 20 };
console.log( name );   // zhangsan
console.log( age );    // 20

上面的例子,var { name: name, age: age } 中,“:”后面的·是 var 将要声明的变量,“:”前面的 name 指定了该变量在赋值符号右面的对象中取哪一个属性的值,在 ES6 中,如果属性名跟属性值的变量名相同时,可以简写。即:

let a = 1;
let b = 2;
let obj = { a: a, b: b }
// 简写
let obj = { a, b }

所以,前面对象解构的例子我们还可以简化一下:

let { name, age } = { name: "zhangsan", age: 20 };
console.log( name );   // zhangsan
console.log( age );    // 20

对象解构的默认值

对象的解构赋值允许指定默认值(下面的示例都省略了 name: ,使用了 ES6 新语法)。

// 没有默认值
let { name } = {};
console.log( name ); // undefined
?
// 有默认值
let { name = "张三" } = {};
console.log( name ); // 张三
?
let { name = "张三", age } = { name: "李四", age: 30 };
console.log( name, age ); // 李四 30

 

5-2 数组基础

数组,英文翻译为 Array,是大多数语言里面最常见的一种数据结构,它是一个有序的值列表,或者说一个有序的数据集合。

JavaScript 中,组成数组的各个值(数据)称为数组中的元素,元素可以是任意数据类型的值,通常我们在同一个数组中只保存同种数据类型的值;数组中元素的个数称为数组的长度,长度为0的数组叫做空数组;数组中的每一个元素都有可以通过一个数字来访问,被称为索引(或称下标),数组索引从 0 开始,所以数组中最后一个元素的索引应该是数组的长度减一。

5-2-1 数组的创建

创建数组的方式大致可以分为两种:字面量创建数组和使用构造函数创建数组。示例如下:

字面量创建数组

let arr1 = [];

构造函数创建数组

let arr1 = new Array();

 

上面的两种方式都创建了一个空数组,需要注意的是,无论是字面量形式创建的数组,还是构造函数创建的数组,当我们使用 typeof 来打印其数据类型的时候,都会返回一个 object,如下:

let arr1 = [];
let arr2 = new Array();
console.log(typeof arr1); // 打印结果:object
console.log(typeof arr2); // 打印结果:object

5-2-2 数组赋值

给数组赋值的方法也非常简单,不过可以分为先声明再赋值和声明时直接赋值,如下:

先声明再赋值

let arr = [];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;

声明时直接赋值

let arr2 = [3,4];// 创建一个长度为2的数组,数组中存放了两个值:3和4
let arr2 = new Array(3,4);// 创建一个长度为2的数组,数组中存放了两个值:3和4

 

我们可以在数组的任意位置进行赋值,数组的长度会自动改变,空的位置使用由于不存在,可以认为全部是 undefined

let arr = [];
arr[0] = 1;
arr[4] = 10;
console.log(arr);
// [ 1, <3 empty items>, 10 ]

由于 JavaScript 是动态语言,所以 JavaScript 里面的数组无法限定其存放数据的数据类型,数组中元素的数据类型可以是任意类型,但是在应用过程中不推荐这样做。

let arr = [1,"Hello",3.14,true];

5-2-3 访问数组元素

通过数组的索引,我们可以轻松的访问到存储在数组里面的元素,如下:

let arr = [1,2,3,4,5];
console.log(arr[0]); // 1

需要注意数组里面的第一个元素是从下标 0 开始的。

除了这种常规的访问方式,我们还可以使用变量的方式来进行访问,如下:

let arr = [1,2,3,4,5];
let i = 2;
console.log(arr[i]); // 3

5-2-4 删除元素

我们可以使用 delete 运算符来删除数组中的某一个元素,示例如下:

let arr = [1,2,3,4,5];
delete arr[2]; // 删除数组中的第3个元素
console.log(arr);
// [ 1, 2, <1 empty item>, 4, 5 ]

###5-2-5 数组的长度

数组的长度,即数组内保存的数据的条数。JavaScript 中为数组提供了一个 length 属性,用来设置或返回数组的长度。

语法结构:

数组名.length

例:

let ary = [100, 200, 300];
// 获取长度
console.log(ary.length);     // 3
// 设置长度
ary.length = 2;
console.log(ary);            // [100, 200]

小技巧:想要快速清空一个数组,就可以将数组的长度赋值为 0。

###5-2-6 多维数组

JavaScript 中的数组有一个特点是可以储存任意类型的数据。也就意味着,数组里面的数据也可以是数组。

let ary = [100, 200, [‘a‘, ‘b‘], 300, 400];

这种数组里面嵌套数组的结构,就叫做多维数组。

多维数组和普通数组的操作方式一样,都是通过下标来实现:

let ary = [100, 200, [‘a‘, ‘b‘], 300, 400];
// 查看
console.log(ary[2][0]);      // ‘a‘
// 修改
ary[2][0] = ‘A‘;
// 新增
ary[5] = [true, false];
// 删除
delete ary[2][0];

###5-2-7 数组的遍历

数组的作用是可以批量保存多条数据,但是当我们需要对数据进行操作时,并不能通过直接操作数组来实现效果,还是需要将每一条数据从数组中取出来,然后再依次取对其进行操作。

数组的遍历就是指依次访问数组中每一项数据。

for 循环

for 循环是遍历数组最简单的一种,也是使用频率最高的一种。

let ary = [100, 200, 300, 400];
// i 即用来控制循环次数,也可用作数组的下标
for(let i = 0; i < ary.length; i++){
   console.log(ary[i]);
}

优化版 for 循环

对于 for 循环的执行流程来说,i < ary.length 这个表达式会反复执行很多次,也就是说,数组的长度每次都要去重新获取。优化版 for 循环就是在普通版 for 循环基础之上,使用临时变量,将数组的长度 ary.length 缓存起来,避免重复获取数组长度。代码如下:

for(let i = 0, len = ary.length; i < len; i++){
   console.log(ary[i]);
}

for-of

ES6 中新增了一种遍历数组的方法 for-of,相比起 for 循环来说它的代码更加简洁。

let ary = [100, 200, 300, 400];
// 创建一个变量 value 用来接收数组中的每一个值
for(let value of ary){
   console.log(value);
}

说明:效率上来说 for-of 还是比不上普通的 for 循环。但是 for-of 除了可以遍历数组外,还可以遍历大多数类数组对象。例如后面会讲到的 SetMap

 

##5-3 数组的常用方法

数组作为一个引用数据类型的对象,包含了很多用于操作数组的方法。这里主要介绍一些比较常用的方法。

###5-3-1 增删数据

数组末尾增删数据

JavaScript 中提供了一组方法,用于对数组末尾的数据进行增加或删除。

  • push:向数组末尾增加多条数据;

  • pop:删除数组末尾的一条数据;

let ary = [100, 200, 300];
ary.push(400, 500, 600);
console.log(ary);   // [100, 200, 300, 400, 500, 600]
ary.pop();
console.log(ary);   // [100, 200, 300, 400, 500]

数组开头增删数据

JavaScript 中提供了一组方法,用于对数组开头的数据进行增加或删除。

  • unshift:向数组开头增加多条数据;

  • shift:删除数组开头的一条数据;

let ary = [100, 200, 300];
ary.unshift(400, 500, 600);
console.log(ary);   // [400, 500, 600, 100, 200, 300]
ary.shift();
console.log(ary);   // [500, 600, 100, 200, 300]

数组任意位置增删数据

JavaScript 中提供了一个万能方法,用于对数组任意位置的数据进行增加或删除。语法结构如下:

数组名.splice(下标, 删除个数, 新增数据1, 新增数据2...);

例:

let ary = [100, 200, 300];
ary.splice(1, 1, 400);    
console.log(ary);    // [ 100, 400, 300 ]

说明:如果不需要删除数据,则 splice 方法的第二个参数为 0。

###5-3-2 查找数据

查找一条数据的下标

JavaScript 中提供了两个方法用来查找某一条数据在数组中的下标。如果没找到对应数据,则返回-1

  • indexOf:查找数据第一次出现的下标;

  • lastIndexOf:查找数据最后一次出现的下标;

语法结构:

数组名.indexOf(数据);
数组名.lastIndexOf(数据);

例:

let ary = [‘hello‘, ‘world‘, ‘hello‘, ‘kitty‘];
?
console.log(ary.indexOf(‘hello‘));       // 0
console.log(ary.lastIndexOf(‘hello‘));   // 2

查找一条数据是否存在

JavaScript 中提供了 includes 方法用来查找某一条数据在数组中是否存在。

语法结构:

数组名.includes(数据)

例:

let ary = [‘hello‘, ‘world‘, ‘hello‘, ‘kitty‘];
?
console.log(ary.includes(‘hello‘));        // true
console.log(ary.includes(‘JavaScript‘));   // false

查找一部分数据

JavaScript 中提供了 slice 方法用来查找数组中的一部分数据,并将找到的数据组成一个新数组。

数据结构:

数组名.slice(起始位置下标, 结束位置下标);

说明:slice 用来查找从起始位置到结束位置(不包含)之间的所有数据。

例:

let ary = [100, 200, 300, 400];
let result = ary.slice(1, 3);
console.log(result);        // [200, 300]

###5-3-3 数据排序

JavaScript 中提供了一组方法,用于操作数组内所有数据的顺序。

  • reverse:将所有数据顺序颠倒;

  • sort:根据给定条件对所有数据进行排序;

let ary = [100, 300, 200, 500, 400];
ary.reverse();
console.log(ary);    // [ 400, 500, 200, 300, 100 ]
ary.sort();
console.log(ary);    // [ 100, 200, 300, 400, 500 ]

sort 方法说明:sort 方法如果省略参数,数组内的数据会先自动通过 toString 方法将值转换成字符串,再按照字符串的比较规则按照从小到大排序。

如果想要按照数字标准进行排序,就需要提供一个比较函数作为参数。语法结构如下:

数组名.sort(function(a, b){
   return a - b;    // 从小到大
   return b - a;    // 从大到小
});

例:

let ary = [100, 300, 200, 500, 400];
ary.sort(function(a, b){
   return a - b;
})
console.log(ary);    // [ 100, 200, 300, 400, 500 ]
?
ary.sort(function(a, b){
   return b - a;
})
console.log(ary);    // [ 500, 400, 300, 200, 100 ]

###5-3-4 数组和字符串转换

JavaScript 中提供了一组方法用户数组和字符串之间的相互转换。

  • join:数组拼接成字符串

  • split:字符串分割成数组(这是字符串的方法)

语法结构如下:

数组名.join(拼接符);
字符串名.split(分割符);

例:

let ary = [100, true, ‘hello‘];
let result = ary.join("-");
console.log(result);    // 100-true-hello
?
let str = "hello, nice to meet you";
let result = str.split(",");
console.log(result);    // [ ‘hello‘, ‘ nice to meet you‘ ]

###5-3-5 数组的遍历

我们讲了数组两种最基本的遍历方式:for 循环和 for-of 。除了这两种以外,数组还提供了很多遍历的方法。

forEach()

自 2009 年 ES5 正式发布后,我们开始可以使用 forEach 方法来遍历数组。

描述:按顺序让数组中每一项依次执行某种相同的操作。

let arr = [10, 11, 12, 13, 14];
?
arr.forEach(function(item, index) {
console.log( item );   // 10 11 12 13 14
console.log( index );  // 0 1 2 3 4
})

图解:

 

图5.1 for-each 遍历

说明:

  • 数组自带的 forEach 循环,使用频率较高,但实际上性能比普通 for 循环弱。

  • forEach不能使用 continue 和 break 语句中断循环,也不能使用 return 语句返回到外层函数。

map()

描述:按顺序让数组中每一项依次执行某种相同的操作,然后返回一个新数组。

let arr = [10, 11, 12, 13, 14];
?
let newArr = arr.map(function(item, index) {
return item * 2;
})
console.log( newArr ); // [20, 22, 24, 26, 28]

图解:

 

图5.2 map 遍历

filter()*

描述:按顺序让数组中每一项依次执行某种相同的操作,然后筛选出符合条件的元素,组成新数组并返回。

let arr = [10, 11, 12, 13, 14];
?
let newArr = arr.filter(function(item, index) {
return item % 2 == 0;
})
console.log(newArr); // [10, 12, 14]

图解:

 

图5.3 filter 遍历

reduce()*

描述:按顺序让数组中的前项和后项做某种计算,并累计返回最终值。

let arr = [10, 11, 12, 13, 14];
?
let result = arr.reduce(function(prev, next) {
return prev + next;
})
console.log(result); // 60

图解:

 

图5.4 reduce 遍历

利用 reduce() 方法的特点,我们还可以通过该方法结合三目运算来求一个数组中的最大或最小值。

let arr = [1, 4, 2, 3, 7, 5];
?
let result = arr.reduce(function(prev, next) {
return prev > next ? prev : next;
})
?
console.log(result);

every()

描述:按顺序让数组中每一项依次执行某种相同的操作,用来检测数组中每一项是否都符合条件。

let arr = [10, 11, 12, 13, 14];
?
let result = arr.every(function(item, index) {
return item % 2 == 0;
})
console.log(result); // false

说明:检测的元素中,如果全部都满足条件,返回 true,只要有一项不满足条件,则返回 false。即一假必假。

图解:

 

图5.5 every 遍历

some()*

描述:按顺序让数组中每一项依次执行某种相同的操作,用来检测数组中某一项是否都符合条件。

let arr = [10, 11, 12, 13, 14];
?
let result = arr.some(function(item, index) {
return item % 2 == 0;
})
console.log(result); // true

说明:检测的元素中,只要有一项符合条件,就返回结果 true,如果全部都不满足条件,则返回结果 false。即一真必真。

图解:

 

图5.6 some 遍历

###5-3-6 遍历方法汇总

方法名描述区别性能(A表示最优)
for 循环 遍历数组 可以使用 break、continue 中断循环 A
for-of 遍历所有复杂数据类型 遍历所有数据的键名 B
forEach() 遍历数组 不可以使用 break、continue 中断循环 C
map() 遍历操作数组元素并返回新数组 返回结果为一个新数组 作用不同,未做性能比较。
filter() 遍历筛选数组元素并返回新数组 返回结果为一个新数组 作用不同,未做性能比较。
reduce() 遍历计算数组元素并累计返回最终值 返回结果为累积计算后的最终值 作用不同,未做性能比较。
every() 遍历检测数组元素,有一项不满足检测条件,则返回 false 返回结果为一个布尔值 作用不同,未做性能比较。
some() 遍历检测数组元素,有一项满足检测条件,则返回 true 返回结果为一个布尔值 作用不同,未做性能比较。

 

##5-4 Set

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值

###5-4-1 基本用法

创建 Set

Set 本身是一个构造函数,调用构造函数用来生成 Set 数据结构。

let s = new Set();

数据初始化

Set 函数可以接受一个数组(或类似数组的对象)作为参数,用来进行数据初始化。

let s = new Set([1, 2, 3, 4, 4]);

通过上面代码运行结果我们可以看到,Set 成员当中如果存在重复的值, 会被自动删除掉。

###5-4-2 Set 实例的属性和方法

Set 结构的实例有以下属性和操作方法。

属性

  • size:返回 Set 实例的成员总数。

let s = new Set([1, 2, 3])
console.log( s.size );   // 3

方法

Set 实例的方法分为两大类:操作方法(用于数据操作)和遍历方法(用于遍历数据)。

操作方法:

  • add(value):添加数据,并返回新的 Set 结构。

  • delete(value):删除数据,返回一个布尔值,表示是否删除成功。

  • has(value):查看是否存在某个数据,返回一个布尔值。

  • clear():清除所有数据,没有返回值。

let set = new Set([1, 2, 3, 4, 4]); 
// 添加数据 5
let addSet = set.add(5);
console.log(addSet);   // Set(5) {1, 2, 3, 4, 5}
// 删除数据 4s
let delSet = set.delete(4);
console.log(delSet);   // true
// 查看是否存在数据 4
let hasSet = set.has(4);
console.log(hasSet);   // false
// 清除所有数据
set.clear();
console.log(set);      // Set(0) {}

遍历方法:

Set 提供了三个遍历器生成函数和一个遍历方法。

  • keys():返回一个键名的遍历器。

  • values():返回一个键值的遍历器。

  • entries():返回一个键值对的遍历器。

  • forEach():使用回调函数遍历每个成员。

let color = new Set(["red", "green", "blue"]);
?
for(let item of color.keys()){
console.log(item);
}
// red
// green
// blue
?
for(let item of color.values()){
console.log(item);
}
// red
// green
// blue
?
for(let item of color.entries()){
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
?
color.forEach((item) => {
console.log(item)
})
// red
// green
// blue

说明:

上例代码中,entries() 方法返回的遍历器,同时包括了键名和键值,所以每次输出一个数组,它的两个成员完全相等。

###5-4-3 与数组相关操作

Set 转数组

由于扩展运算符...内部的原理也是使用的 for-of 循环,所以也可以用于操作 Set 结构。

例如将 Set 结构转换为数组结构:

let color = new Set(["red", "green", "blue"]);
let colorArr = [...color];

数组剔重

扩展运算符和 Set 结构相结合,就可以去除数组的重复成员。

let arr = [1, 1, 2, 2, 3, 3];
let unique = [...new Set(arr)];     // [1, 2, 3]

 

##5-5 Map

JavaScript 中的对象(Object),本质上是键值对的集合,但是只能用字符串来做键名。这给它的使用带来了很大的限制。

为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

也就是说,Object 结构提供了“字符串 - 值”的对应,Map 结构提供了“值 - 值”的对应,是一种更完善的 JSON 数据结构的实现。如果你需要“键值对”的数据结构,MapObject 更合适。

###5-5-1 基本用法

创建 Map

Map 本身是一个构造函数,在使用构造函数时,通过传入参数进行数据初始化

Map 函数也可以接受一个数组(或类似数组的对象)作为参数,用来进行初始化。但是跟 Set 不同的是,Map 中该数组中的成员是一对对表示键值对的数组。

let m = new Map([["name", "zhangsan"], ["age", 20]]);
console.log( m );

###5-5-2 Map 实例的属性和方法

Map 结构的实例有以下属性和方法。

属性

  • size:返回 Map 结构的成员总数。

let m = new Map([["name", "zhangsan"], ["age", 20]]);
console.log( m.size );

方法

Map 实例的方法也分为了两大类:操作方法(用于数据操作)和遍历方法(用于遍历数据)。

操作方法:

  • set(key, value):添加或修改数据。设置 key 所对应的键值,并返回 Map 结构本身。

  • get(key):获取数据。读取 key 对应的键值,如果找不到 key,返回 undefined

  • has(key):查看是否存在某个数据,返回一个布尔值。

  • delete(key):删除数据。删除成功返回 true

  • clear():清除所有数据,没有返回值。

let map = new Map([["name", "zhangsan"], ["age", 20]]);
// 设置 name 的值为 lisi
map.set("name", "lisi");
console.log( map );       // Map(2) {"name" => "lisi", "age" => 20}
// 获取 name 对应的值
let getMap = map.get("name");
console.log( getMap );    // lisi
// 查看是否存在 age
let hasMap = map.has("age");
console.log( hasMap );    // true
// 删除 age 键值对
let delMap = map.delete("age");
console.log( delMap );    // true
// 清空所有数据
map.clear();
console.log(map);         // Map(0) {}

Map 提供了三个遍历器生成函数和一个遍历方法:

  • keys():返回一个键名的遍历器。

  • values():返回一个键值的遍历器。

  • entries():返回一个键值对的遍历器。

  • forEach():使用回调函数遍历每个成员。

let num = new Map([["one", 1], ["two", 2], ["three", 3]]);
?
for(let key of num.keys()){
console.log(key);
}
// one
// two
// three
?
for(let value of num.values()){
console.log(value);
}
// 1
// 2
// 3
?
for(let item of num.entries()){
console.log(item[0], item[1]);
}
// one 1
// two 2
// three 3
?
// 将上面代码通过解构改成如下
for(let [key, value] of num.entries()){
console.log(key, value);
}
// one 1
// two 2
// three 3
?
num.forEach((value, key) => {
console.log(value, key)
})
// 1 one
// 2 two
// 3 three

5-5-3 与其他数据结构互换

Map 转为数组

Map 转为数组最方便的方法,就是使用扩展运算符...

let myMap = new Map();
myMap
.set(true, "真")
.set(false, "假");
console.log(myMap);   // {true => "真", false => "假"}
let newMap = [...myMap];
console.log(newMap);  // [[true, "真"], [false, "假"]]

 

图5.7 Map 类型变量使用扩展运算符

数组转为 Map**

将数组传入 Map 构造函数中,就可以转为 Map

let arr = [[true, "真"], [false, "假"]];
let map = new Map(arr);
console.log(map);   // {true => "真", false => "假"}

Map 转为对象

如果 Map 所有的键都是字符串,它就可以转为对象。

function strMapToObj(strMap){
let obj = {};
for(let [k, v] of strMap){
obj[k] = v;
}
return obj;
}
?
let myMap = new Map().set("green","绿").set("red","红");
console.log(myMap);                  // {"green" => "绿", "red" => "红"}
console.log( strMapToObj(myMap) );   // { green: "绿", red: "红" }

对象转为 Map

function objToStrMap(obj){
let strMap = new Map();
for(let item in obj){
strMap.set( item, obj[item] )
}
return strMap;
}
?
let obj = { name: "zhangsan", age: 20 };
console.log( objToStrMap(obj) );    
// {"name" => "zhangsan", "age" => 20}

 

总结

本章主要为读者介绍了引用数据类型,以及一个新的概念数据结构。不管是对象,还是数组,SetMap,它们都可以用来组织存放数据,我们把他们都叫做数据结构。

其中,对象的创建,对象属性和方法的基本操作和使用是我们认识引用数据类型的知识基础。我们也要学会使用其它的数据结构,合理的选择,才能写出更好的代码。

对于数组,它的特点是有序,这就要求我们关注数组的索引;对于 Set ,它的特点是不重复,那我们就可以通过它来排除重复;对于 Map ,它的特点是键值对(k-v),如果要处理映射关系,我们可以考虑它。而不管是哪一个数据结构,除了学会它的基本操作“增删查改”以外,我们也要学会怎么去遍历它们。

 

以上是关于引用数据类型的主要内容,如果未能解决你的问题,请参考以下文章

Android App 在片段中创建 ListView 引用时关闭

引用向量的部分片段?

片段对话框对活动的松散引用

Android 我应该在异步任务中将片段作为弱引用传递吗?

变量的内存分析图

复合(或引用)数据类型图解:及例题代码