箭头函数
参数
1 2 3 4 5 6 7 8 9
| var f = (v) => v; console.log(f(1));
var f = function (v) { console.log(v); }; f();
|
1 2 3
| var f1 = () => 5; console.log(f1());
|
1 2 3
| var f2 = (a, b) => a + b; console.log(f2(3, 4));
|
- 箭头函数里没有
arguments
,可以...rest
来接过来
1 2 3 4 5 6 7 8 9
| let fn = (...arg) => { console.log("arg", arg); }; function fn1() { console.log(arguments); } fn(1, 2, 3, 4); fn1(1, 2, 3, 4);
|
参数默认值
箭头函数里的默认值可以写在参数里
1 2 3 4 5 6 7 8 9 10 11 12 13
| function fn() { a = a || 1; b = b || 2; return a + b; }
let fnES6 = (a = 1, b = 2) => { return a + b; }; console.log(fnES6(10, 20)); console.log(fnES6());
|
用法 & 问题
- 箭头函数不能直接返回对象,他会当作代码块去处理,解决方法:在对象外 套上圆括号 即可
1 2 3 4 5
|
var f3 = (hi) => ({ name: "小强", age: 18 }); console.log(f3(1));
|
1 2 3 4
| let { log: l } = console; var f4 = () => {}; l(f4());
|
- 把很多实参捏到一起,变成真正的数组,用
...arr
,也叫做 rest
1 2 3 4
| let { log: l } = console; var f5 = (...arr) => arr; l(f5(1, 2, "33", 4, "5"));
|
1 2 3 4
| let { log: l } = console; var arr_map = [1, 2, 3, 4].map((items) => items + 1); l(arr_map);
|
1 2 3
| var arr_sort = [100, 5, 74, 998].sort((a, b) => a - b); l(arr_sort);
|
与 this 的联系
用了箭头函数,那么 this 指向的就是对象,而不是谁调用就指谁了
1 2 3 4 5 6 7 8 9 10 11 12
| let fn; let fn2 = function () { console.log("fn2--this:>>", this); fn = () => { console.log("fn--this:>>", this); }; };
fn2 = fn2.bind(document.body);
fn2(); fn();
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function f8() { setTimeout(function () { console.log(this); }, 1000); } function f8_jiantou() { setTimeout(() => { console.log(this); }, 4000); }
var obj_f8 = { name: "f8Name", }; f8.call(obj_f8);
f8_jiantou.call(obj_f8);
|
再来一个例子慢慢理解一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function foo() { return () => { return () => { console.log(this.id); }; }; } var foo1 = foo.call({ id: "一" }); console.log(foo1);
var foo2 = fun1.call({ id: "二" }); console.log(foo2);
foo2();
|
总结:箭头函数它本身没有this
,调用建通函数的this
时, 指向的是其声明时所在的作用域的this
缺点
1 2 3 4
| var F = () => {}; var f = new F(); f();
|
1 2 3 4 5 6
| var fun3 = () => { console.log(arguments); }; fun3(123);
|
处理错误
- 一般由
try
、catch
、finally
、throw
几个构成
try
:尝试执行代码,这里遇到的第一个错误会带到 catch
中
catch
:处理错误,可以把错误吞并掉,从而避免卡住浏览器
finally
:无论 try
中出错与否,都会执行
throw
:抛尸,比方说 throw new error("你输错了");
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <body> <h3>请输入6~100</h3> <input type="text" id="inp"> <button id="btn">这是一个测试</button> </body>
<script> var btn = document.querySelector("#btn"); var inp = document.querySelector("#inp"); btn.onclick = function () { try{ if(inp.value < 6){ throw new error("你输错了"); } }catch (err) { console.log(err); inp.value = ''; }finally { console.log("吃瓜群众") } } </script>
|
数据结构:set
这个数据结构的特点是:元素不会重复
它没有下标,没有所谓的 length 长度
规则
- 重复元素的判断跟
===
差不多,不同的是 NaN
,如果有两个 NaN
,他会认成一个,也就是书面一样
1 2 3
| let set = new Set([NaN, NaN]); console.log(set);
|
1 2 3
| let set = new Set([0, -0]); console.log(set);
|
1 2 3
| let set = new Set([1, "1"]); console.log(set);
|
长度
1 2 3 4 5 6
| let set = new Set([1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 6, "5", NaN, NaN]); console.log(set.size);
console.log(set.length);
|
增加元素
1 2 3 4
| let set = new Set([]); set.add("8848钛金手机"); console.log(set);
|
删元素
- 用
set.delete()
删除元素,返回布尔值,表示成功与否
1 2 3 4 5 6 7
| let set = new Set(["8848钛金手机"]); console.log(set);
set.delete("8848钛金手机"); console.log(set);
|
查找元素
- 用
set.has("");
查找元素,返回布尔值表示,true 为存在
1 2 3 4
| let set = new Set(["8848钛金手机"]);
console.log(set.has("8848钛金手机"));
|
遍历
遍历可以用如下的方法
- 用
Array.from(set)
- 结构解析
[...set]
forEach
循环
1 2 3 4 5 6 7
| var set1 = new Set([1, 2, 3, 4, 3, 2, 1]);
console.log(Array.from(set1));
console.log([...set1]);
|
1 2 3 4 5 6
| let set = new Set(["甲", "乙", "丙", "丁"]); set.forEach((item) => console.log(item));
|
清空
1 2 3 4 5 6 7
| let set = new Set(["8848钛金手机"]); console.log(set);
set.clear(); console.log(set);
|
曲线救国实现 map 方法
1 2 3 4 5
| var set = new Set([1, 1, 2, 2, 3, 3, 4, 4, 5, 5]);
var map = new Set([...set].map((item) => item + 10)); console.log(map);
|
数组去重
用 set 的特性啊,没有重复的元素
想得到么小伙子
1 2
| console.log([...new Set([1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3])]);
|
求两个 set 元素的交集
关键,用过滤器 filter
,他会保留返回值是 true
的
1 2 3 4 5
| let set1 = new Set([1, 2, 3, 4, 5, 9]); let set2 = new Set([1, 2, 5, 6, 7, 8, 9]); let result_jiaoji = [...set1].filter((items) => set2.has(items)); console.log(result_jiaoji);
|
WeakSet
- 只能添加 Object 的 set
- WeakSet 不允许被循环,因为内部保存的对象的值是弱引用的,如果这些对象没有使用了,那么它将会被垃圾回收机制给收走,所以就没办法枚举了。
- WeakSet 里面放节点-防止内存泄露-JC
转载:知乎-WeakSet 的用法解惑
MDN:WeakSet
1 2 3 4 5 6 7 8 9 10 11 12 13
| var weakset = new WeakSet(); var set = new Set([1]); var obj = { name: "1", };
weakset.add(obj); console.log(weakset);
weakset.add(1);
|
1 2 3 4 5 6 7
| var weakset = new WeakSet(); weakset.add([ [1, 2], [1, 2], ]); console.log(weakset);
|
数据类型 Symbol
ES 6 中又新添加了个数据类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let s1 = Symbol("这里是描述s1"); let s2 = Symbol("这里是描述s2");
console.log(s1 == s2);
console.log(typeof s1);
console.log(s1.toString() + "1");
|
- 建议放在对象中做属性名(因为它的特性–永远不会重复)
1 2 3 4 5 6 7 8 9 10 11
| let s1 = Symbol(); let s2 = Symbol(); const obj = { [s1]: "string1", [s2]: "string2", }; console.log(obj[s1]);
console.log(obj[s2]);
|
- 用
Object.keys()
是拿不出来 Symbol 的,根据这个特性,可以伪装成私有属性,for in
循环更是白扯,啥都不输出
1 2 3 4 5 6 7 8 9 10 11 12
| let s1 = Symbol(); let s2 = Symbol(); const obj = { [s1]: "string1", [s2]: "string2", }; for (let x in obj) { console.log(x); } console.log(Object.keys(obj));
|
取值
它有自己的方法 Object.getOwnPropertySymbols(obj)
1 2 3 4 5 6 7 8 9 10
| let s1 = Symbol(); let s2 = Symbol(); const obj = { [s1]: "string1", [s2]: "string2", };
console.log(obj[Object.getOwnPropertySymbols(obj)[0]]);
|
Symbol.for()
Q:有人就想问,Symbol 既然是独一无二的,真的就不能重用么?
引进新的方法:Symbol.for();
只要描述相同的话,那么他俩就是相同的
1 2 3 4 5 6 7 8 9 10 11 12
| let a = Symbol("a");
let b = Symbol.for("b");
let c = Symbol.for("b");
console.log(a == b);
console.log(b == c);
|
取 ‘ 描述 ’
symbol.description
可以拿出属性
Symbol.keyFor(b)
只能拿出 Symbol.for("")
设定的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| let a = Symbol("a"); let b = Symbol.for("b"); let c = Symbol.for("b");
console.log(a.description);
console.log(b.description);
console.log(Symbol.keyFor(b));
console.log(Symbol.keyFor(a));
|
魔术字符
就是出现频率贼 JB 高,改起来贼 JB 费劲,一改就要改一大堆的的字符串就叫做魔术字符
官方说法:我们把 耦合性极强,复用性极差,出现频率极高 的字符串成为魔术字符
1 2 3 4 5 6 7 8 9
|
function test(mon) { if (mon == "6") { } else if (mon > "6") { } else if (mon < "6") { } }
|
那解决的方法蛮多的,用个变量代替它不就好了。要改的话,就改变量的值就好了
1 2 3 4 5 6 7 8 9 10
| const obj = { key: "value", }; function test(mon) { if (mon == obj.key) { } else if (mon > obj.key) { } else if (mon < obj.key) { } }
|
深入理解 Object 和 Map
Object
- 对象结构来源于:hash 结构
- 对象的 key 是会自动
toString
的
- 是 string - value 的组合
Map
- map 的 key 值没有 toString,很自由,想放什么放什么
- 是 value - value 的组合
1 2 3 4 5 6 7 8 9 10 11 12
| const map = new Map(); map.set({ name: 1 }, 2); console.log(map.get({ name: 1 }));
var obj_kong = {}; console.log(obj_kong == {});
|