文章目錄
箭頭函數
參數
- 最簡單的箭頭函數:一個形參可以不用括號
var f = v => v;
console.log(f(1));
//1
//這就等同於
var f = function (v) {
console.log(v)
};
f();
- 函數如果沒有形參,需要加括號
var f1 = () => 5;
console.log(f1());
//5
- 多參數也需要加括號
var f2 = (a,b) => a + b;
console.log(f2(3,4));
//7
用法 & 問題
- 箭頭函數不能直接返回對象,他會當作代碼塊去處理,解決方法:在對象外 套上圓括號 即可
//不能直接返回對象
//解決:在對象外加 ()
var f3 = hi => ({name:"小強",age:18});
console.log(f3(1));
//{name: "小強", age: 18}
- 函數如果沒有返回值,打印的是
undefined
let {log:l} = console;
var f4 = () => {};
l(f4());
//undefined
- 把很多實參捏到一起,變成真正的數組,用
...arr
,也叫做rest
let {log:l} = console;
var f5 = (...arr) => arr;
l(f5(1,2,'33',4,"5"));
//(5) [1, 2, "33", 4, "5"]
- 和
map
映射結合,把數組中的每一項都加1
let {log:l} = console;
var arr_map = [1,2,3,4].map(items => items + 1);
l(arr_map);
//(4) [2, 3, 4, 5]
- 和
sort
結合,進行從小到大排序
var arr_sort = [100,5,74,998].sort((a,b) => a-b);
l(arr_sort);
//(4) [5, 74, 100, 998]
與 this 的聯繫
用了箭頭函數,那麼 this 指向的就是對象,而不是誰調用就指誰了
//看這個例子
function f8() {
setTimeout(function () {
console.log(this)
},1000)
}
function f8_jiantou() {
setTimeout( () => {
console.log(this)
},4000)
//當定時器的函數體擴回後,定時器又重新是windows的了
//當定時器的函數體擴回前,定時器是一直指向obj_f8的
}
var obj_f8 = {
name:"f8Name"
};
f8.call(obj_f8);
//Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}
//這裏把 obj_f8 的指針給了f8_jiantou,那麼定時器裏的this 就指向obj_f8
f8_jiantou.call(obj_f8);
//{name: "f8Name"}
再來一個例子慢慢理解一下
function foo () {
return () => {
return () =>{
console.log(this.id);
}
}
}
var foo1 = foo.call({id:"一"});
console.log(foo1);
/*() => {
return () =>{
console.log(this.id);
}
}*/
var foo2 = fun1.call({id:"二"});
console.log(foo2);
/*() =>{
console.log(this.id);
}*/
foo2();
//一
缺點
- 不能使用箭頭函數實例化對象了
var F = () =>{
};
var f = new F;
f();
//Uncaught TypeError: F is not a constructor
- 不能用 arguments 獲取傳來的參數了
/*3.不能使用arguments*/
var fun3 = () => {
console.log(arguments);
};
fun3(123);
//Uncaught ReferenceError: arguments is not defined
處理錯誤
- 一般由
try
、catch
、finally
、throw
幾個構成 try
:嘗試執行代碼,這裏遇到的第一個錯誤會帶到catch
中catch
:處理錯誤,可以把錯誤吞併掉,從而避免卡住瀏覽器finally
:無論try
中出錯與否,都會執行throw
:拋屍,比方說throw new error("你輸錯了");
<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) {
//try裏遇到第一個錯誤之後會攜帶錯誤信息跳到catch裏
//會把error喫掉,不會卡住瀏覽器,會繼續渲染
console.log(err);
//處理錯誤
inp.value = '';
}finally {
//不管有沒有錯誤都要執行
console.log("喫瓜羣衆")
}
}
</script>
數據結構:set
這個數據結構的特點是:元素不會重複
它沒有下標,沒有所謂的 length 長度
規則
- 重複元素的判斷跟
===
差不多,不同的是NaN
,如果有兩個NaN
,他會認成一個,也就是書面一樣
let set = new Set([NaN,NaN]);
console.log(set);
//Set(1) {NaN}
let set = new Set([0,-0]);
console.log(set);
//Set(1) {0}
let set = new Set([1,"1"]);
console.log(set);
//Set(2) {1, "1"}
長度
- 用
set.size
let set = new Set([1,1,1,2,2,3,3,3,4,5,6,"5",NaN,NaN]);
console.log(set.size);
//8
console.log(set.length);
//undefined
增加元素
- 用
set.add()
let set = new Set([]);
set.add("8848鈦金手機");
console.log(set);
//Set(1) {"8848鈦金手機"}
刪元素
- 用
set.delete()
刪除元素,返回布爾值,表示成功與否
let set = new Set(["8848鈦金手機"]);
console.log(set);
//Set(1) {"8848鈦金手機"}
set.delete("8848鈦金手機");
console.log(set);
//Set(0) {}
查找元素
- 用
set.has("");
查找元素,返回布爾值表示,true 爲存在
let set = new Set(["8848鈦金手機"]);
console.log(set.has("8848鈦金手機"));;
//true
遍歷
遍歷可以用如下的方法
- 用
Array.from(set)
- 結構解析
[...set]
forEach
循環
var set1 = new Set([1,2,3,4,3,2,1])
/*只要有遍歷器接口的都可以用forOf遍歷*/
console.log(Array.from(set1));
//(4) [1, 2, 3, 4]
console.log([...set1]);
//(4) [1, 2, 3, 4]
let set = new Set(["甲","乙","丙","丁"]);
set.forEach((item) => console.log(item));
//甲
//乙
//丙
//丁
清空
- 用
set.clear();
來清空
let set = new Set(["8848鈦金手機"]);
console.log(set);
//Set(1) {"8848鈦金手機"}
set.clear();
console.log(set);
//Set(0) {}
曲線救國實現 map 方法
var set = new Set([1,1,2,2,3,3,4,4,5,5]);
//先把set結構解析成數組,然後用數組的map
var map = new Set([...set].map(item => item + 10));
console.log(map);
//Set(5) {11, 12, 13, 14, 15}
數組去重
用 set 的特性啊,沒有重複的元素
想得到麼小夥子
console.log([...new Set([1,2,3,1,2,3,1,2,3,1,2,3])]);
//(3) [1, 2, 3]
求兩個 set 元素的交集
關鍵,用過濾器 filter
,他會保留返回值是 true
的
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);
//(4) [1, 2, 5, 9]
WeakSet
- 只能添加 Object 的 set
- WeakSet 不允許被循環
- WeakSet 裏面放節點-防止內存泄露-JC
var weakset = new WeakSet();
var set = new Set([1]);
var obj = {
name:'1'
};
//添加一個對象
weakset.add(obj);
console.log(weakset);
//WeakSet {{…}}
//如果想要添加一個數字,他會報錯
weakset.add(1);
//Uncaught TypeError: Invalid value used in weak set
- 如果想添加個數組
var weakset = new WeakSet();
weakset.add([[1,2],[1,2]]);
console.log(weakset);
//WeakSet {Array(2)}
數據類型 Symbol
ES 6 中又新添加了個數據類型
- 他的值 獨一無二
let s1 = Symbol("這裏是描述s1");
let s2 = Symbol("這裏是描述s2");
console.log((s1 == s2));
//false
console.log((typeof s1));
//symbol
//console.log(s1 + "1");
//Uncaught TypeError: Cannot convert a Symbol value to a string
//不能隱式轉換,能顯示轉換
console.log((s1.toString() + '1'));
//Symbol(這裏是描述s1)1
- 建議放在對象中做屬性名(因爲它的特性–永遠不會重複)
let s1 = Symbol();
let s2 = Symbol();
const obj = {
[s1]:"string1",
[s2]:"string2"
};
console.log(obj[s1]);
//string1
console.log(obj[s2]);
//string2
- 用
Object.keys()
是拿不出來 Symbol 的,根據這個特性,可以僞裝成私有屬性,for in
循環更是白扯,啥都不輸出
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));
//(2) [Symbol(), Symbol()]
取值
它有自己的方法 Object.getOwnPropertySymbols(obj)
let s1 = Symbol();
let s2 = Symbol();
const obj = {
[s1]:"string1",
[s2]:"string2"
};
//這個可以拿出來以Symbol爲key的
console.log(obj[Object.getOwnPropertySymbols(obj)[0]]);
//string1
Symbol.for()
Q:有人就想問,Symbol 既然是獨一無二的,真的就不能重用麼?
引進新的方法:Symbol.for();
只要描述相同的話,那麼他倆就是相同的
let a = Symbol("a");
//重用,第一個Symbol.for("b")相當於註冊
let b = Symbol.for("b");
//之後Symbol.for("b")是尋找,並且把b的指針給c
let c = Symbol.for("b");
console.log((a == b));
//false
console.log((b == c));
//true
取 ‘ 描述 ’
symbol.description
可以拿出屬性Symbol.keyFor(b)
只能拿出Symbol.for("")
設定的屬性
let a = Symbol("a");
let b = Symbol.for("b");
let c = Symbol.for("b");
console.log(a.description);
//a
console.log(b.description);
//b
//主要拿Symbol.for的description的
console.log(Symbol.keyFor(b));
//b
console.log(Symbol.keyFor(a));
//undefined
魔術字符
就是出現頻率賊 JB 高,改起來賊 JB 費勁,一改就要改一大堆的的字符串就叫做魔術字符
官方說法:我們把 耦合性極強,複用性極差,出現頻率極高 的字符串成爲魔術字符
//例子
//這裏的字符串 '6' 就稱之爲魔術字符
//這是判斷語句少的情況,多了的話改起來就費勁了
function test(mon) {
if(mon == "6"){
}else if(mon > "6"){
}else if(mon < "6"){
}
}
那解決的方法蠻多的,用個變量代替它不就好了。要改的話,就改變量的值就好了
//這樣改唄
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 的組合
const map = new Map();
map.set({name:1},2);
console.log(map.get({name:1}));
//undefined
//這裏的undefined是因爲
//map.get({name:1}) 中,又新建了一個{name:1}
//這個跟set裏的對象,雖然內容一樣,但是指針不同
//相當於
var obj_kong = {};
console.log((obj_kong == {}));
//false