Leetcode 24. Swap Nodes in Pairs
一、新增資料型別Symbol。
概念:
Symbol代表獨一無二的
Symbol型別的值通過Symbol函式來生成,同時Symbol函式生成的值是唯一的
Symbol函式何以接收字串作為引數,但是即使相同引數返回的值也是唯一的
作用:
屬性私有化
資料保護
//沒有引數的情況 let s1 = Symbol(); let s2 = Symbol(); s1 === s2 //false //有引數的情況 let s1 = Symbol("fun"); let s2 = Symbol("fun"); s1 === s2 //false let mySymbol = Symbol(); //第一種寫法 let a = {}; a[mySymbol] = "Hello!"; //第二種寫法 let a = { [mySymbol]: "Hello!" } //第三種寫法 let a = {}; Object.defineProperty(a,mySymbol,{value: "Hello!"}); //列舉Symbol的key值 Object. getOwnPropertySymbols(obj); //注意,Symbol作為物件的key值不能被for in進行遍歷。
二、塊級作用域。
概念:在ES6中,凡事{}包裹的程式碼都是跨級作用域,凡事在塊級作用域中用let、const宣告的變數都有一個暫時性死區。
{ let a = 20; } console.log(a); //報錯
三、var、let、const宣告變數。
var
支援變數宣告與解析
不支援塊級作用域
可以重複宣告。
let
不支援變數宣告與解析
支援塊級作用域
不可以重複宣告
用let宣告的變數或者方法只能在程式碼塊中生效。
{ let a = 10; var b = 20; } console.log(a); //報錯 console.log(b); //20
const
不支援變數宣告與解析
支援塊級作用域
不可以重複宣告
宣告變數,一旦宣告不可修改
宣告變數必須賦值,不可以像var一樣先聲明後再定義。
四、解構賦值。
概念:允許按照一定格式,從物件和陣列中提取值。
//陣列解構 let [a,b,c] = [1,2,3]; console.log(a,b,c); //1,2,3 //物件解構,物件解構時key值必須要一一對應。 let {name,age} = {name: "張三",age: 20}; console.log(name,age); //張三 20 //物件解構+別名 let {name: _name, age: _age} = {name: "張三", age: 20}; console.log(_name,_age); //張三 20 //多重解構 let {obj:{name},arr:[a,b]} = {obj:{name: "張三"},arr: [10,20]};
五、擴充套件運算子
概念:將陣列或物件轉換成引數序列,使用逗號分割的序列。
作用:
1、陣列、物件的合併
2、函式剩餘引數
3、替代arguments
//數組合並 let arr1 = [10,20,30]; let arr2 = [40,50,60]; let newArr = [...arr1,...arr2]; console.log(newArr); //[10,20,30,40,50,60]; //展開陣列 console.log(Math.Max(...arr)); //物件合併 let obj1 = {width: 100, height: 100}; let obj2 = {left: 100, top: 100}; let newObj = {...obj1,...obj2}; console.log(newObj); //{width:100,height:100,left:100,top:100};
六、字串模版。
1、字串太長需要換行怎麼辦?
//常規解決辦法 var a = "<div>" + "<span>"+num+"</span>" "</div>"; //ES6語法 let a = `<div> <span>${num}</span> </div>`
2、字串太長怎麼辦?
let phone = 15844423232
let intro = `my name is chj, my phone id ${phone}`;
3、includes字串搜尋。
//ES6神器,includes方法,str.insludes(內容),找到了返回true,沒找到返回false let str = "good method!"; str.includes("method"); //true
4、判斷首尾,startsWith endsWith
/* startsWith判斷是否位於頭部 endsWith判斷是否位於尾部 這兩個方法是includes的擴充套件 */ let str = "how are you?"; str.startsWith("how"); //true str.endsWith("?") //true
5、repeat字串重複
//str.repeat(n); 將字串重複n次 let str = "abc"; str.repeat(3); //abcabcabc
七、物件新增方法。
1、物件的簡寫
let a = 10; let obj = {a}; //等價於 let obj = {a: 10}; //當key值和value值一樣的時候我們可以寫一個。
2、Object.is
//判斷兩個物件是否指向同一個記憶體地址 let obj1 = {a: 1, b: 2}; let obj2 = obj1; Object.is(obj1, obj2); //true
3、Object.assign
//合併物件 let obj1 = {name: '曹海傑', age: 20}; let obj2 = {sex: '男'}; let newObj = Object.assign(obj1, obj2); console.log(newObj); //{name: '曹海傑', age: 20, sex: '男'};
八、陣列中新增的方法。
1、Array.of()
//將一組值轉換為陣列 let arr = Array.of(1,2,3,4); console.log(arr); //[1,2,3,4];
2、Array.from()
//將偽陣列轉換為陣列。 let aLi = Array.from(document.getElementsByTagName("li")); console.log(aLi instanceof Array); //instanceof判斷某物件是否屬於某類的例項。
3、Array.find()
//通過條件查詢資料,返回第一個符合條件的資料。 let arr = [1,2,3,4]; let n = arr.find(function(item, index, array) { return item > 3; }) console.log(n); //4
4、Array.findIndex()
//查詢陣列中符合條件的資料的下標,如果沒有找到則返回undefined let arr = [1,2,3,4]; let n = arr.findIndex(function(item, index , array) { return item > 3; }) console.log(n);
5、Array.fill();
//對陣列進行填充,語法:arr.fill('內容',開始下標,結束下標); let arr = [1,2,3,4]; arr.fill('qwe', 1, 3); console.log(arr); //[1, 'qwe', 'qwe', 4];
九、for of and for in
/* 1、for of 是ES6的,for in 是ES5的 2、for of 遍歷的是值,for in遍歷的是鍵 3、for of 不能遍歷物件,for in 既可以遍歷物件也可以遍歷陣列 4、for of 遍歷陣列的時候,如果有未定義的項,遍歷出來的是undefined,for in 則遍歷不到 5、for of 不能遍歷到原型上定義的屬性(自定義屬性),for in 可以遍歷到 6、for of 的相容性不是很好,移動端安卓微信瀏覽器不支援,Safari支援 */ Array.prototype.hehe = '呵呵'; let arr = [1,2,3, ,4]; for (let item of arr) { console.log(item); //1,2,3,undefined,4 } for (let prop in arr) { console.log(prop); //0,1,2,4,hehe } let obj = { name: 'chj', age: 20 } for (let item of obj) { //報錯 console.log(item); } for (let prop in obj) { console.log(prop); //name age }
十、函式
1、函式引數預設值
//ES6之前函式怎麼設定預設值 function fn(x) { let x= x || 10; } //ES6函式預設值,等價於上面的寫法,如果沒有傳遞引數,就使用預設值10 function fn(x=10) { }
2、剩餘引數
//fn函式中a接收實參1,...rest接收剩餘引數為一個數組。 funciton fn(a, ...rest) { console.log(...rest); //[2,3,4,5]; } fn(1,2,3,4,5);
3、箭頭函式
//語法一 function 換成 () => let fn = (a) => { console.log(a) } //語法二 不寫{}預設表示return,當前函式意思是返回a這個值 let fn = a => a fn(10); //語法三 不寫{}預設表示return,當前函式表示返回一個物件 let fn = a => ({a:1}); /* 箭頭函式特點: 1、this指向離自己最近的外層作用域的物件 2、不能當作建構函式使用(箭頭函式是匿名函式,沒有函式名字所以沒有辦法new) 3、沒有arguments這個引數(ES6已經取消arguments這個引數了) 4、不能當作generator函式 */
十一、Set集合
/* Set: 集合 1、類似於陣列,但成員的值是唯一的,沒有重複的值,並且是無序的 2、Set是一個建構函式 3、Set每次執行完畢後都會返回一個Set,因此可以進行鏈式呼叫 */ let s = new Set(); //新增 add() s.add("a").add("b"); console.log(s); //Set(2) {"a","b"}; //刪除 返回值是一個布林值 s.delete("a") ; //true //判斷元素是不是Set的成員,返回值是一個布林值 s.has("a"); //true //清除所有 沒有返回值 s.clear(); //返回所有鍵名 s.keys(); //返回所有value值 s.values(); //返回所有鍵值對 s.entries(); //可以通過for of 遍歷每一個值 for(let item of s) { console.log(s); }
十二、Map字典型別結構
/* 1、字典:用來儲存不重複key的hash結構,不同於Set集合,字典使用[鍵,值]的形式來儲存 2、Map執行完畢後都會返回一個Map,可以進行鏈式呼叫 3、特點:普通物件只能通過字串來當作key值,但是Map可以使用任何值來當作key值 */ //建立Map物件 let map = new Map({ ["a", 1], ["b", 2] }) console.log(map); //Map(2) {"a" => 1, "b" => 2} //獲取map長度 map.size //新增陣列 map.set("c",3) //獲取map值 map.get("a") //刪除資料 刪除成功返回true map.delete("a") //檢測map中是否含有某個值 返回布林值 map.has("a") //清除所有資料 map.clear(); //獲取所有key值 map.keys(); //獲取所有value值 map.values(); //獲取所有鍵值對 map.entries(); //遍歷map物件 index在前item在後(陣列中item在前) map.forEach((index, item) => { console.log(index, item); })
十三、Proxy介紹
概念:Proixy是ES6中新增的一個特性。
作用:在目標物件之前架設一層“攔截”,外界對該物件的訪問,都必須想通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫,很類似於設計模式中的代理模式。
基本用法:
let p = new Proxy(target, handler);
引數:
target: 用Proxy包裝被代理的物件(可以是任意型別的物件,包括原生陣列、函式、甚至是另一個代理)
handler:是一個物件,其聲明瞭代理target的一些操作,其屬性是當執行一個操作時定義代理的行為的函式
特點:
1、可以劫持整個物件,並返回一個新物件
2、有13中劫持操作
3、handler代理的一些常用方法:
get 讀取
set 修改
has 判斷物件是否有該屬性
construct 建構函式
apply 當目標物件是一個函式的時候
deletePrototy 用於攔截delete操作
十四、get/set方法
let target = { name: "chj", age: 20, sex: "男" } let p = new Proxy(target, { get(obj, attr) { console.log("屬性被訪問了"); }, set(obj, attr, value) { console.log("屬性被設定了"); } }) p.name; p.name = "小王";
get函式:當訪問target物件身上的一些屬性的時候就會觸發get函式,get函式接收兩個引數
引數一:代理的物件,也就是target。
引數二:訪問的屬性。
set函式:當設定target物件身上的一些屬性的時候就會觸發set函式,set引數接收三個引數
引數一:代理的物件
引數二:設定物件的屬性
引數三:設定物件的屬性的值
使用場景:
1、虛擬場景
let target = { firstName: "chj", lastName: "ls" } let p = new Proxy(target, { get(obj, attr) { if(attr == "fullName") { retrun [obj.firstName, obj.lastName].join(" "); } return obj[attr]; }, set(obj, attr, value) { if(attr == "fullName") { let fullNameInfo = value.split(" "); obj.firstName = fullNameInfo[0]; obj.lastName = fullNameInfo[1]; }else { obj[attr] = value; } } }) console.log(fullName); //chj p.fullName = "小 甜甜"; console.log(p.firstName); //小 console.log(p.lastName); //甜甜
2、私有屬性
//把_開頭的變數都認為私有變數 let target = { name: "張三", age: 20, _sex: "女" } let p = new Proxy(target, { get(obj, attr) { if(attr.startWith("_")) { console.log("私有屬性不被允許訪問"); return false; } return obj[attr]; }, set(obj, attr, value) { if(attr.startWith("_")) { console.log("私有屬性不允許設定"); retrun false; } obj[attr] = value; }, has(obj, attr) { if(atrr.startWith("_")) { return false; } retrun (attr in obj); } })
十五、函式攔截
apply:當目標物件是一個函式,且他被呼叫時,就是被apply方法攔截
引數:apply(target, context, arguments) {}
target:目標物件
context:目標物件的上下文(this)
arguments:目標物件的引數陣列
construct:用於攔截new命令,意思就是你在new目標物件的時候,會走construct() {}
引數:construct(target, arguments) {}
target:目標物件
arguments:建構函式的引數物件
function fn(a, b) { lat handler = { apply: function(target, context, args) { console.log(target, context, args) return args[0]; }, construct: function(target, args) { return {value: args[1]}; } } }; let p = new Proxy(fn, handler); console.log(p(1, 2)) //1 console.log(new p(1, 2)) //{value: 2}