ES6 Map 数据结构、ES6 箭头函数
目录
Map 定义与基本用法
Map 属性与方法
Map 遍历
ES6 箭头函数
箭头函数基本用法
简化回调函数
Map 定义与基本用法
JavaScript 的对象(Object)本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键,这给它的使用带来了很大的限制。
为了解决这个问题,ES6 提供了 Map 数据结构,它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Map 对 象</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
/**map:创建一个 Map 对象
* json:创建一个 json 对象*/
let map = new Map();
const json = {"name": "Hua An"};
/**赋值:第一个 key 为对象 json,第二个 key 为字符串 "json" */
map.set(json, 'content');
map.set("json", json);
console.log(map.get(json)); // 根据 key 取值:"content"
console.log(map.has(json)); // 判断是否存在某个 Kye:true
console.log(map.delete(json));//删除某个 key:true
console.log(map.has(json)); // 判断是否存在某个 Kye:false
console.log(map.get("json")["name"]);//根据 Key 取值,然后取 json 的值:Hua An
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
作为构造函数,Map 也可以接受一个数组作为参数,该数组的成员是一个个表示键值对的数组。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Map 对 象</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
/**创建一个 json 对象*/
const json = {"name": "Hua An"};
/**map:创建一个 Map 对象,同时初始化值*/
const map = new Map(
[
['name', '张三'],
['title', 'Author'],
["user", json]
]);
console.log(map.size);// 3
console.log(map.has('name'));//判断是否存在某个 Kye: true
console.log(map.get('name'));// 根据 key 取值:"张三"
console.log(map.has('title'));// 判断是否存在某个 Kye:true
console.log(map.get('title'));// 根据 key 取值:"Author"
console.log(map.get("user")["name"]);// "Hua An"
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
事实上,不仅仅是数组,任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作 Map 构造函数的参数。这就是说,Set 和 Map 都可以用来生成新的 Map 。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Map 对 象</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
let mapSource = new Map();
mapSource.set("name", "华安");
mapSource.set("title", "宁王造反");
let map = new Map(mapSource);
console.log(map.size);// 2
console.log(map.get('name'));// 根据 key 取值:"华安"
console.log(map.get('title'));// 根据 key 取值:"宁王造反"
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
如果对同一个键多次赋值,后面的值将覆盖前面的值,如果读取一个未知的键,则返回undefined。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Map 对 象</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
let map = new Map();
map.set("name", "华安");
map.set("name", "宁王造反");
console.log(map.size);// 1
console.log(map.get('name'));// 根据 key 取值:"宁王造反"
console.log(map.get('title'));// 根据 key 取值:undefined
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
只有对同一个对象的引用,Map 结构才将其视为同一个键,Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Map 对 象</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
let map = new Map();
/**
* 内存地址是不一样的,所以 k1 与 k2 是两个不同的对象
* @type {string[]}
*/
let k1 = ["name", "华安"];
let k2 = ["name", "华安"];
map.set(k1, "我是 k1");
map.set(k2, "我是 k2");
console.log(map.size);// 2
console.log(map.get(k1));// 根据 key 取值:我是 k1
console.log(map.get(k2));// 根据 key 取值:我是 k2
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
如果 Map 的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map 将其视为一个键,比如0和-0就是一个键,布尔值true和字符串true则是两个不同的键。另外,undefined和null也是两个不同的键。虽然NaN不严格相等于自身,但 Map 将其视为同一个键。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Map 对 象</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
let map = new Map();
map.set(-0, 123);
map.set(-5, 456);
console.log(map.get(+0));// 123
console.log(map.get(5));// undefined
console.log(map.get(-5));// 456
map.set(true, 1);
map.set('true', 2);
console.log(map.get(true));// 1
console.log(map.get("true"));// 2
map.set(undefined, 3);
map.set(null, 4);
console.log(map.get(undefined));// 3
console.log(map.get(null));// 4
map.set(NaN, 123);
console.log(map.get(NaN));// 123
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
Map 属性与方法
size 属性返回 Map 结构的成员总数:
let map = new Map([
["name", "华安"],
["age", 35]
]);
console.log(map.size);//输出 2
let map2 = new Map();
console.log(map2.size);//输出 0
set(key,value) 方法设置键名 key 对应的键值为 value,然后返回整个 Map 结构。如果 key 已经有值,则键值会被更新,否则就新生成该键:
let map = new Map();
map.set("name", "张三");
map.set(123, "age");
map.set(undefined, "未定义");
console.log(map);//输出 {"name" => "张三", 123 => "age", undefined => "未定义"}
/**set方法返回的是原 Map 对象,所以可以链式编程*/
map.set("name", "华安").set(123, "年龄");
console.log(map);//输出 {"name" => "华安", 123 => "年龄", undefined => "未定义"}
get(key) 方法读取 key 对应的键值,如果找不到 key,返回 undefined:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>ES6 测试</title>
<!-- JQuery CDN-->
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="module">
$(function () {
let map = new Map();
map.set("name", "华安").set("age", 35);
map.set("address", "苏州");
console.log(map.get("name"), map.get("age"), map.get("address"), map.get("birthday"));
//输出:华安 35 苏州 undefined
});
</script>
</head>
<body>
</body>
</html>
has(key) 方法返回一个布尔值,表示某个键是否在当前 Map 对象之中:
let map = new Map();
map.set("name", "华安").set("age", 35);
map.set(110, "公安局");
console.log(map.has("name"), map.has("age"), map.has(110));//输出:true true true
console.log("abc");//输出:false
delete(key) 方法删除某个键,返回 true。如果删除失败,返回 false:
let map = new Map();
map.set("name", "华安").set("age", 35);
map.set(110, "公安局");
console.log(map.has("name"), map.has("age"), map.has(110));//输出:true true true
console.log(map.delete("name"));//输出:true
console.log(map.delete(110));// 输出:true
console.log(map.has("name"), map.has("age"), map.has(110));//输出:false true false
clear 方法清除所有成员,没有返回值:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>ES6 测试</title>
<!-- JQuery CDN-->
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="module">
$(function () {
let map = new Map();
map.set("name", "华安").set("age", 35);
map.set(110, "公安局");
console.log(map.size);//输出:3
map.clear();
console.log(map.size);//输出:0
});
</script>
</head>
<body>
</body>
</html>
Map 遍历
Map 结构原生提供三个遍历器生成函数和一个遍历方法, 需要特别注意的是,Map 的遍历顺序就是插入顺序。
• keys():返回键名的遍历器。
• values():返回键值的遍历器。
• entries():返回所有成员的遍历器。
• forEach():遍历 Map 的所有成员。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>增强 For 循环</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
let map = new Map([
["name", "赵子龙"],
["age", 35],
["address", "常山"]
]);
console.log("--------1------");
// 依次输出:name、age、address
for (let keyLoop of map.keys()) {
console.log(keyLoop);
}
console.log("--------2------");
//依次输出:赵子龙、35、常山
for (let valueLoop of map.values()) {
console.log(valueLoop);
}
console.log("--------3------");
//依次输出:name 赵子龙、age 35、address 常山
/**其中循环的 item 相当于 Java 中 Map 迭代时的 Entry*/
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
console.log("--------4------");
//依次输出:name 赵子龙、age 35、address 常山
/**上面可以简写如下*/
for (let [keyLoop,valueLoop] of map.entries()) {
console.log(keyLoop, valueLoop);
}
console.log("--------5------");
//依次输出:name 赵子龙、age 35、address 常山
/**上面可以再简写如下*/
for (let [keyLoop,valueLoop] of map) {
console.log(keyLoop, valueLoop);
}
//依次输出:name 赵子龙、age 35、address 常山
console.log("--------6------");
map.forEach(function (value, key) {
console.log(key, value);
})
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
ES6 箭头函数
箭头函数基本用法
ES6 允许使用“箭头”(=>)定义函数。如下所示当函数带一个参数时:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>箭头函数</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- ES6 时,script 的 type 需要标识成 module,否则箭头函数编译不通过,即无法识别-->
<script type="module">
let f1 = param => param;
/**函数 f1 等价于函数 f2 */
let f2 = function (param) {
return param;
}
$(function () {
console.log(f1(3));// 输出 3
console.log(f2(5));// 输出 5
});
</script>
</head>
<body>
</body>
</html>
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>箭头函数</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- ES6 时,script 的 type 需要标识成 module,否则箭头函数编译不通过,即无法识别-->
<script type="module">
let getTime1 = () => new Date();
/**函数 getTime1 等价于函数 getTime2 */
let getTime2 = function () {
return new Date();
}
$(function () {
console.log(getTime1());// 输出系统当前时间
console.log(getTime2());// 输出系统当前时间
});
</script>
</head>
<body>
</body>
</html>
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,如果需要返回,则使用 return 语句返回:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>箭头函数</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- ES6 时,script 的 type 需要标识成 module,否则箭头函数编译不通过,即无法识别-->
<script type="module">
let sun1 = (a, b) => {
return a + b;
}
/**函数 sun1 等价于 sun2 */
let sun2 = function (a, b) {
return a + b;
}
let sun3 = (a, b)=> {
console.log(a + b);
}
$(function () {
console.log(sun1(10, 20));// 输出 30
console.log(sun2(20, 30));// 输出 50
sun3(30, 40);//输出 70
});
</script>
</head>
<body>
</body>
</html>
由于大括号被解释为代码块,所以如果箭头函数直接返回一个 Json 对象,必须在对象外面加上括号,否则会编译报错:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>箭头函数</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- ES6 时,script 的 type 需要标识成 module,否则箭头函数编译不通过,即无法识别-->
<script type="module">
let getUserJson1 = (id, name) =>({"id": id, "name": name});
/**
* 函数 getUserJson1 等价于 getUserJson2,不过 getUserJson1 更简洁
* getUserJson1 中因为想要返回一个 json 对象,所以为了不让大括号 {} 起冲突,外面必须加 ()
* getUserJson2 是 getUserJson1 的拆解写法,语义上更好理解
* @param id
* @param name
* @returns {
{id: *, name: *}}
*/
let getUserJson2 = (id, name) => {
let userJson = {"id": id, "name": name};
return userJson;
}
$(function () {
let userJson1 = getUserJson1("9527", "华安");
let userJson2 = getUserJson2("8888", "宁王");
console.log(JSON.stringify(userJson1));//输出:{"id":"9527","name":"华安"}
console.log(JSON.stringify(userJson2));//输出:{"id":"8888","name":"宁王"}
});
</script>
</head>
<body>
</body>
</html>
箭头函数可以与变量解构结合使用,如 参数可以直接转换 json 对象:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>箭头函数</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- ES6 时,script 的 type 需要标识成 module,否则箭头函数编译不通过,即无法识别-->
<script type="module">
/**
* 参数中 {id,name} 会直接解构传入的 json 对象
* @param id
* @param name
*/
let getUserInfo1 = ({id,name})=>"id=" + id + ",name=" + name;
/**函数 getUserInfo1 等价于 getUserInfo2*/
let getUserInfo2 = function (userInfo) {
return "id=" + userInfo.id + ",name=" + userInfo.name;
}
$(function () {
let userInfo = {"id": 9527, "name": "华安"};
console.log(getUserInfo1(userInfo));//输出 id=9527,name=华安
console.log(getUserInfo2(userInfo));//输出 id=9527,name=华安
});
</script>
</head>
<body>
</body>
</html>
箭头函数使得表达更加简洁:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>箭头函数</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- ES6 时,script 的 type 需要标识成 module,否则箭头函数编译不通过,即无法识别-->
<script type="module">
/**
* isEven 函数判断一个数是否为偶数
* square 函数用于球平方
* @param n
*/
let isEven = n => n % 2 == 0;
let square = n => n * n;
$(function () {
console.log(isEven(0));// 输出 true
console.log(isEven(2));// 输出 true
console.log(isEven(3));// 输出 false
console.log(square(5));// 输出 25
});
</script>
</head>
<body>
</body>
</html>
简化回调函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>箭头函数</title>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- ES6 时,script 的 type 需要标识成 module,否则箭头函数编译不通过,即无法识别-->
<script type="module">
$(function () {
let arr1 = [1, 2, 3, 4, 5];
/**正常函数写法,可以参考:https://blog.csdn.net/wangmx1993328/article/details/84066490*/
let arr1_new1 = arr1.map(function (value) {
return value * value;
});
/**
* 上面等价于下面的箭头函数写法
* @type {Array}
*/
let arr1_new2 = arr1.map(value=>value * value);
console.log(arr1_new1.toString());//输出 1,4,9,16,25
console.log(arr1_new2.toString());//输出 1,4,9,16,25
});
</script>
</head>
<body>
</body>
</html>
箭头函数有几个使用注意点。
(1)函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用 new 命令,否则会抛出一个错误。
(3)不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。
上面四点中,第一点尤其值得注意。this 对象的指向是可变的,但是在箭头函数中,它是固定的。
还没有评论,来说两句吧...