javascript
javascript的ES6学习总结(第三部分)
1.ES6中的面向對象的類
1.1、定義類
在ES5中,我們寫一個類,通常是這么寫的
function Person(name,age){this.name = name;this.age = age; } /*** es5中的模擬面向對象的類的方法 寫法1 Person.prototype.showName = function(){return "名字為:"+this.name; } Person.prototype.showAge = function(){return "年齡為:"+this.age; }*//*** es5中的模擬面向對象的類的方法 寫法2**/ Object.assign(Person.prototype,{showName(){return "名字為:"+this.name;},showAge(){return "年齡為:"+this.age;} }); var p1 = new Person('tom',18); console.log(p1.showName());//名字為:tom console.log(p1.showAge());//年齡為:18在ES6中,我們可以這樣寫
//ES6中的類(類名大小寫都可以,推薦使用規范按照首字母大寫) class Person{constructor(name,age){//構造方法(函數),每new一個新對象,自動執行// console.log(`構造函數執行了,${name},${age}`);//構造函數執行了,Lucy,18this.name = name;this.age = age;}showName(){return `名字為:${this.name}`;}showAge(){return `年齡為:${this.age}`;} } let p1 = new Person('Lucy',18); console.log(p1.showName(),p1.showAge());//名字為:Lucy 年齡為:18 //ES6中的類(賦給一個變量或常量,類名大小寫都可以,推薦使用規范首字母大寫) const Person = class{constructor(name,age){//構造方法(函數),每new一個新對象,自動執行// console.log(`構造函數執行了,${name},${age}`);//構造函數執行了,Lucy,18this.name = name;this.age = age;}showName(){return `名字為:${this.name}`;}showAge(){return `年齡為:${this.age}`;} } let p1 = new Person('Lucy',18); console.log(p1.showName(),p1.showAge());//名字為:Lucy 年齡為:18注意:
(1).ES6里面Class沒有提升(例如ES5中的函數有提升到頂部的作用)
(2).ES6中的this,首先來看一下ES5中矯正this的幾個方法
(2.1) fn.call(this指向誰,args1,args2...);
(2.2) fn.apply(this指向誰,[args1,args2...]);
(2.3) fn.bind();(React中經常會用到)
其中,(2.1) fn.call和(2.2) fn.apply都會在矯正this的時候,方法(函數)會調用一次
class Person{constructor(){this.name = 'jason';this.showName = this.showName.bind(this);//矯正this}showName(){console.log('this:',this);//this: Person {name: "jason", showName: function}return `名字為:${this.name}`;} } let p1 = new Person(); let {showName} = p1; console.log(showName());//名字為:jason1.2、類里面的取值函數(getter)和存值函數(setter):
class Person{constructor(name){this.name = name;}get aaa(){return `獲取aaa的名字,值為${this.name}`;}set aaa(val){console.log(`設置aaa的名字,值為${val}`);} } let p1 = new Person('jack'); console.log(p1.aaa);//獲取aaa的名字,值為jack p1.aaa = 'luke';//設置aaa的名字,值為luke1.3、類里面的靜態方法(就是類身上的方法)
class Person{constructor(){}showName(){return '這是showName方法';}static aaa(){return '這是靜態方法';} } let p1 = new Person(); console.log(p1.showName());//這是showName方法 console.log(Person.aaa());//這是靜態方法1.4、類里面的繼承
先來回顧一下ES6之前的繼承寫法
1.原型鏈繼承
//父類 Animal.prototype.eat = function(food) {console.log(this.name + '正在吃' + food); } function Animal(name) {this.color = ['green','red','blue'];this.name = name || 'animal';this.sleep = function() {console.log(this.name + "正在睡覺")} }原型鏈繼承核心:?將父類的實例作為子類的原型。
//子類 function Cat(name) {this.name = namethis.color = ['green','red','blue'];//引用類型值,,所有實例會共享這個屬性。 } Cat.prototype = new Animal(); var cat = new Cat('cat'); console.log(cat.name); console.log(cat.eat('fish')); console.log(cat instanceof Animal); console.log(cat.sleep());缺點:
但是,原型鏈式繼承并沒有實現代碼的復用,一些共同的屬性:如name,在子類中還是得重新寫一遍(即同一套代碼還是得重新寫)。
再者,cat繼承了Animal實例的所有屬性和方法,這些方法并不都是我們需要的,也就是過多的繼承了沒有用的屬性。且如果原型中包含引用類型值,那么所有的實例會共享這個屬性。
2.構造函數繼承
function Person(name,age,sex){this.name = name;this.age = age;this.sex = sex; } function Student(name,age,sex){Person.call(this,name,age,sex);this.grade = grade; } let student = new Student;優點:
- 構造函數模式繼承實現了代碼的復用
缺點:
- 不能繼承借用的構造函數的原型,只能借用構造函數本身的屬性和方法
- 每次構造函數都要多走一個函數
3.組合繼承
// 父類 function Person(name){this.name = name; } Person.prototype.showName = function(){return `名字是:${this.name}` }; // 子類 function Student(name,age){Person.call(this,name);//繼承屬性,在創建實例時第二次調用Personthis.age = age; } Student.prototype = new Person();//繼承方法,第一次調用Person Student.prototype.constructor = Student;//矯正constructor Student.prototype.sayName = function(){return '年齡是:'+this.age; } // 調用 var stu1 = new Student('jack',20); console.log(stu1.name);//jack console.log(stu1.showName);//function (){return `名字是:${this.name}`} console.log(stu1.showName());//名字是:jack console.log(stu1.sayName());//年齡是:20缺點:
- 父類構造函數被調用2次,子類實例的屬性存在兩份,一份在原型上,一份在實例屬性上。造成內存的浪費。
4.寄生組合式繼承
寄生組合式繼承是對組合繼承的進一步優化。我們先看一下為什么要寫這個語句。
SubType.prototype = new SuperType();我們無非是想讓SubType繼承SuperType的原型。但是我們為什么不直接寫成這樣呢?
SubType.prototype = SuperType.prototype這樣寫確實可以實現子類對象對父類對象原型的繼承。但是這樣寫的話:所有繼承該父類的子類對象的原型都指向同一個了。也就是說SubType不能有自己的原型了。這顯然不是我們想要的。
既然不能直接繼承,那可不可以間接繼承SuperType.prototype呢。這就是最終的解決方案:寄生組合式繼承。
我們讓一個函數去指向SuperType.prototype,然后讓SubType.prototype指向這個函數產生的對象不就可以了嘛。
function inherit(Target,Origin) {//實現寄生組合式繼承的核心函數function F() {};F.prototype = Origin.prototype; //F()的原型指向的是OriginTarget.prototype = new F(); //Target的原型指向的是F()Target.prototype.constructor = Target; SubType.prototype.__proto__ == SuperType.prototype }function SuperType(name) {this.name = name;this.colors = ['red','blue','pink']; } SuperType.prototype.sayName = function() {console.log(this.name); } function SubType(name,age) {//繼承屬性SuperType.call(this,name);//在創建實例時第二次調用SuperTypethis.age = age; }inherit(SubType,SuperType);//實現寄生組合式繼承我們再來看一下實現寄生組合式繼承的核心函數。F函數其實是通用的,我們沒必要每次進入inherit函數時都聲明一遍。所以我們可以用閉包的形式來寫:
var inherit = (function () {var F = function () {};return function (Target , Origin) {F.prototype = Origin.prototype;//F()的原型指向的是OriginTarget.prototype = new F();//Target的原型指向的是F()Target.prototype.constructor = Target;Target.prototype.uber = Origin.prototype;SubType.prototype.__proto__ == SuperType.prototype}})()再來看看ES6繼承的寫法,相比前面就優雅了許多,代碼量也會少很多!!!
/* ES6繼承 */ // 父類 class Person{constructor(name){this.name = name;}showName(){return `名字為:${this.name}`;} } // 子類 class Student extends Person{} // 調用 var stu1 = new Student('jack'); console.log(stu1.showName());//名字為:jack子類在自己的身上加方法:
/* ES6繼承 */ // 父類 class Person{constructor(name){this.name = name;}showName(){return `名字為:${this.name}`;} } // 子類 class Student extends Person{constructor(name,skill){super(name);//子類的構造函數必須有super(),相當于執行一次父級的構造函數this.skill = skill;}showSkill(){return `他的名字是${this.name},他的特長是${this.skill}`;} } // 調用 var stu1 = new Student('jack','跳舞'); console.log(stu1.showSkill());//他的名字是jack,他的特長是跳舞如果子類的方法和父類的方法同名,然后想調用父類的方法,自己子類的方法也要執行,可以這么寫
/* ES6繼承 */ // 父類 class Person{constructor(name){this.name = name;}showName(){console.log('父類的showName');return `名字為:${this.name}`;} } // 子類 class Student extends Person{constructor(name,skill){super(name);//子類的構造函數必須有super(),相當于執行一次父級的構造函數this.skill = skill;}showName(){super.showName();//執行父類的方法/* 這里寫子類自己的要做的事 */console.log('子類的showName');}showSkill(){return `他的名字是${this.name},他的特長是${this.skill}`;} } // 調用 var stu1 = new Student('jack','跳舞'); console.log(stu1.showName());//父類的showName 子類的showName2.Symbol和Generator
2.1Symbol:ES6新增的一種數據類型
定義方法:let Symbol = Symbol('aaa');
注意:
(1)Symbol不能當new來使用
(2)Symbol()返回是一個唯一值
(3)Symbol是一個單獨數據類型,就叫symbol的基本類型
(4)如果Symbol作為key,用for in循環,出不來
let symbol = Symbol('Jack'); let json = {a:'apple',b:'banana',[symbol]:'aaa' } console.log(json[symbol]);//aaa // 遍歷json for(let key in json){console.log(key);//a b }2.2Generator生成器函數:解決異步,深度嵌套的問題
語法:
function * show(){} function* show(){} function *show(){}定義&調用:
function * gen(){//在函數名前面使用*號定義一個yield 'hello';yield 'javascript';return 'generator函數'; } let g1 = gen(); console.log(g1.next());//Object {value: "hello", done: false} console.log(g1.next());//Object {value: "javascript", done: false} console.log(g1.next());//Object {value: "generator函數", done: true} console.log(g1.next());//Object {value: undefined, done: true}遍歷generator函數:
function * gen(){//在函數名前面使用*號定義一個yield 'hello';yield 'javascript';yield 'world';return 'generator函數'; } let g1 = gen(); /*遍歷generator函數(注意:return的東西不會被遍歷出來)*/ // 1.用for...of遍歷 for(let val of g1){console.log(val);//hello javascript world } // 2.使用解構 let [a,b,c,d] = gen(); console.log(a,b,c,d);//hello javascript world undefined // 3.使用擴展(三個點)運算符 let [f,...g] = gen(); console.log(f,g);//hello ["javascript", "world"] let [...newArr] = gen(); console.log(newArr);//["hello", "javascript", "world"] //4.使用Array.from函數 console.log(Array.from(gen()));//["hello", "javascript", "world"]關于異步的解決方案:
(1)回調函數
(2)事件監聽
(3)發布/訂閱
(4)Promise對象
(5)Generator函數
(6)Async/Await
3.async、await函數:解決異步問題
定義:在函數前面加async,函數內部加await,后面的代碼會等待前面的代碼先執行
語法:
async function fn(){//表示異步,這個函數里面有異步的任務let result=await;//表示后面結果需要等待 }使用(例如讀取文件):
(1)promise寫法:
const fs = require('fs');// 用fs封裝一個promise const readFile = function(fileName){return new Promise((resolve,reject)=>{fs.readFile(fileName,(err,data)=>{if(err) reject(err);resolve(data);})}) }// promise readFile('data/1.txt').then(res=>{console.log(res.toString());return readFile('data/2.txt'); }).then(res=>{console.log(res.toString()); });(2)generator寫法:
const fs = require('fs');// 用fs封裝一個promise const readFile = function(fileName){return new Promise((resolve,reject)=>{fs.readFile(fileName,(err,data)=>{if(err) reject(err);resolve(data);})}) }// generator function * gen(){yield readFile('data/1.txt');yield readFile('data/2.txt'); } let g1 = gen(); g1.next().value.then(res=>{console.log(res.toString());return g1.next().value; }).then(res=>{console.log(res.toString());return g1.next().value; });(3)async、await寫法:
// 用async、await做一個文件讀取 const fs = require('fs');// 用fs封裝一個promise const readFile = function(fileName){return new Promise((resolve,reject)=>{fs.readFile(fileName,(err,data)=>{if(err) reject(err);resolve(data);})}) }// async async function fn(){//表示異步,函數內有異步任務let f1 = await readFile('data/1.txt');//表示后面的結果需要等待 console.log(f1.toString());let f2 = await readFile('data/2.txt');console.log(f2.toString()); } fn();async、await特點:
1.await只能放在async函數中
2.相比generator語法更強
3.await后面可以是promise對象,也可以是數字、字符串、布爾類型
4.async函數返回的是一個promise對象
5.只要await語句后面Promise狀態變為reject,那么整個async函數會中斷執行
如何解決async函數中拋出錯誤,影響后續代碼執行?
1.使用try{}catch(e){}語法
async function fn(){try{await Promise.reject('出現問題了');}catch(e){}let a = await Promise.resolve('successs');console.log(a); } fn().then(res=>{console.log(res); }).catch(err=>{console.log(err); }); // 結果 // success undefined2.promise本身的catch
async function fn(){let [a,b] = await Promise.all([readFile('data/1.txt'),readFile('data/2.txt')]);console.log(a.toString());console.log(b.toString()); } fn();4.Set和WeakSet
4.1、Set數據結構:類似數組,但里面不能有重復值。new Set([]),存儲數組
用法:
// Set數據結構 let setArr = new Set(['a','b','a']); console.log(setArr);//Set(2) {"a", "b"}方法:
(1)add()方法:向Set數據結構中添加元素
// Set數據結構--add()方法:向數組中添加元素 let setArr = new Set(); setArr.add('aaa'); setArr.add('bbb'); setArr.add('aaa'); console.log(setArr);//Set(2) {"aaa", "bbb"} // add()方法鏈式添加 let setArr = new Set().add('aaa').add('bbb').add('aaa'); console.log(setArr);//Set(2) {"aaa", "bbb", "ccc"}(2)delete()方法:刪除Set數據結構中的某一項
let setArr = new Set(); setArr.add('aaa'); setArr.add('bbb'); setArr.add('ccc'); console.log(setArr);//Set(2) {"aaa", "bbb","ccc"} // Set數據結構--delete()方法:刪除Set數據結構中的某一項 setArr.delete('bbb'); console.log(setArr);//Set(2) {"aaa", "ccc"}(3)clear()方法:刪除Set數據結構中的所有項
// Set數據結構--add()方法:向Set數據結構中添加元素 let setArr = new Set(); setArr.add('aaa'); setArr.add('bbb'); setArr.add('ccc'); // Set數據結構--clear()方法:刪除Set數據結構中的所有項 setArr.clear(); console.log(setArr);//Set(0) {}(4)has()方法:檢測Set數據結構中的是否某一項,返回布爾值
let setArr = new Set(); setArr.add('aaa'); setArr.add('bbb'); setArr.add('ccc'); // Set數據結構--has()方法:檢測Set數據結構中的是否某一項,返回布爾值 console.log(setArr.has('bbba'));//false(5)size屬性:查看Set數據結構有多少個元素
let setArr = new Set(); setArr.add('aaa'); setArr.add('bbb'); setArr.add('ccc'); // Set數據結構--size屬性:查看Set數據結構有多少個元素 console.log(setArr.size);//3(6)循環Set數據結構(注:Set數據結構的key和value是相同的)
for(let val of setArr){//默認循環的是values()console.log(val);//aaa bbb ccc } console.log('-------'); for(let val of setArr.keys()){console.log(val);//aaa bbb ccc } console.log('-------'); for(let val of setArr.values()){console.log(val);//aaa bbb ccc } for(let item of setArr.entries()){console.log(item);//["aaa", "aaa"] ["bbb", "bbb"] ["ccc", "ccc"] } for(let [k,v] of setArr.entries()){console.log(k,v);//aaa aaa bbb bbb ccc ccc } setArr.forEach((val,index)=>{console.log(val,index);//aaa aaa bbb bbb ccc ccc });利用Set做數組的去重:
方法1
let arr = [1,2,3,4,5,6,3,4,5,3,2]; let newArr = [...new Set(arr)];//這里數組去重返回的是一個數組的淺拷貝 arr.push(9,8,7,7,8); console.log(arr);//[1, 2, 3, 4, 5, 6, 3, 4, 5, 3, 2, 9, 8, 7, 7, 8] console.log(newArr);//[1, 2, 3, 4, 5, 6]方法2
let arr2 = [1,2,3,4,5,6,3,4,5,3,2]; let newArr2 = new Set(); arr2.map(x=>newArr2.add(x)); let resArr2 = [...newArr2]; console.log(resArr2);[1, 2, 3, 4, 5, 6]4.2、WeakSet數據結構:類似數組對象,但里面不能有重復值。new WeakSet({}),存儲對象
注意:
1.WeakSet初始化定義時,不能在里面存值。
2.WeakSet里面的add()方法只能存json對象,如果存字符串、數字等會報錯!
定義:
let set = new WeakSet();//WeakSet初始化定義時,不能在里面存值。 let json = {a:1,b:2 }; let json2 = {a:'asp',b:2 }; set.add(json); set.add(json2);//add()方法只能存json對象,如果存字符串、數字等會報錯! //set.add(true);//Invalid value used in weak set console.log(set);//WeakSet {Object {a: "asp", b: 2}, Object {a: 1, b: 2}}方法:Set數據結構提供的方法除了size屬性和clear()方法沒有,別的都有。(例如:add()、has()、delete())
5.Map和WeakMap
5.1Map數據結構:類似json,但是json的鍵(key)只能是字符串,而map的key可以是任意類型
使用:
// Map使用 let map = new Map(); map.set(key,value);方法:
// Map使用 let map = new Map(); let json = {a:1,b:2 }// map.set(key,value);//設置一個值 map.set('abc','123'); map.set(json,'aaa'); map.set('a',json); console.log(map);//Map(3) {"abc" => "123", Object {a: 1, b: 2} => "aaa", "a" => Object {a: 1, b: 2}}// map.get(key);//獲取一個值 console.log(map.get(json));//aaa console.log(map.get('a'));//Object {a: 1, b: 2}// map.delete(key);//刪除某一項 map.delete('abc'); console.log(map);//Map(2) { Object {a: 1, b: 2} => "aaa", "a" => Object {a: 1, b: 2}}// map.has(key);//查找某一項,返回布爾值 console.log(map.has('abc'));//false// map.clear();//刪除所有項 map.clear(); console.log(map);//Map(0) {}循環map數據結構:
let map = new Map(); let json = {a:1,b:2 } map.set('abc','123'); map.set(json,'aaa'); map.set('a',json); // 循環map for(let [key,value] of map){//默認entries console.log(key,value);/*abc 123Object {a: 1, b: 2} "aaa"Object {a: 1, b: 2}*/ } for(let key of map.keys()){} for(let value of map.values()){} for(let [key,value] of map.entries()){} map.forEach((value,key)=>{console.log(key,value);/*abc 123Object {a: 1, b: 2} "aaa"Object {a: 1, b: 2}*/ });5.1WeakMap數據結構:類似json,但是json的鍵(key)只能是字符串,而WeakMap的key只能是對象
使用:
// WeakMap使用 let wmap = new WeakMap(); let json = {a:1,b:2 } wmap.set(json,'123'); console.log(wmap);//WeakMap {Object {a: 1, b: 2} => "123"}總結:
1.Set ?里面是數組,不能重復,沒有key(下標),沒有get方法
2.Map 對json功能增強,key可以是任意類型值
6.數字變化和Math新增的東西
6.1數字變化(數值變化)
1.進制:
// 二進制:(binary) let a = 0b010101; console.log(a);//21 // 八進制:(Octal) let b = 0o652; console.log(b);//426 // 十六進制:(Hexadecimal) let c = 0xabc; console.log(c);//27482.數值判斷
// 數字變化 let a = 12; // Number.isNaN:判斷是否為NaN console.log(Number.isNaN(a));//false // Number.isFinite:判斷是否是數字 let b = 'aaa'; console.log(Number.isFinite(b));//fasle // Number.isInteger:判斷是否是整數 let c = 12.12; console.log(Number.isInteger(c));//false console.log(Number.isInteger(a));//true // Number.parseInt():將一個數據轉換成整數 console.log(Number.parseInt(2.5)); // Number.parseFloat():將一個數據轉換成浮點數 console.log(Number.parseFloat("13.5526"));//13.5526 // Number.isSafeInteger():判斷是否是安全整數 /* 安全整數:-(2^53-1)到(2^53-1) */ console.log(Number.isSafeInteger(-(2**53)));//false console.log(Number.isSafeInteger(-(2**53-1)));//true console.log(Number.isSafeInteger((2**53)));//false console.log(Number.isSafeInteger((2**53-1)));//true // Number.MAX_SAFE_INTEGER:最大安全整數 console.log(Number.MAX_SAFE_INTEGER);//9007199254740991 // Number.MIN_SAFE_INTEGER:最小安全整數 console.log(Number.MIN_SAFE_INTEGER);//-90071992547409916.2Math新增的東西
// Math新增的東西 // Math.trunc():截取數字整數部分 console.log(Math.trunc(4.6));//4 // Math.sign():判斷一個數是正數、負數、0 console.log(Math.sign(-5));//-1 console.log(Math.sign(5));//1 console.log(Math.sign(0));//0 console.log(Math.sign(-0));//-0 console.log(Math.sign('abc'));//NaN // Math.cbrt():計算一個數的立方根 console.log(Math.cbrt(27));//3 // ...等等7.ES2018(ES9)新增的東西
7.1命名捕獲(用于正則匹配)
語法:(?<名字>)
以前寫正則,要把捕獲到的數據賦給變量,都是這么寫的
let today = "2019-05-03"; let reg = /(\d{4})-(\d{2})-(\d{2})/; let dateArr = today.match(reg); let [full,year,month,day,...more] = dateArr; console.log(year,month,day);//2019 05 03現在,我們可以這么寫:
let today = "2019-05-03"; let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;//建議在Chrome瀏覽器下測試,別的瀏覽器可能會報錯。 let {year,month,day} = today.match(reg).groups; console.log(year,month,day);//2019 05 037.2反向引用命名捕獲
1.反向引用以前寫法:
(1)\1 \2(字符串寫法) ? ?(2)$1 $2(str.replace()方法寫法)
語法:\k<名字>
如果要匹配和前面組相同的多個,可以這么寫
// 匹配:"monday-monday" // let reg = /^(?<m>monday)-\k<m>$/; // let str = 'a-a'; // let str2 = 'm-m'; // let str3 = 'monday-monday'; // console.log(reg.test(str));//false // console.log(reg.test(str2));//false // console.log(reg.test(str3));//true// 匹配:"monday-monday-monday" let reg = /^(?<m>monday)-\k<m>-\1$/;//或者let reg = /^(?<m>monday)-\k<m>-\k<m>$/; let str = 'a-a'; let str2 = 'm-m'; let str3 = 'monday-monday'; let str4 = 'monday-monday-monday'; console.log(reg.test(str));//false console.log(reg.test(str2));//false console.log(reg.test(str3));//false console.log(reg.test(str4));//true2.替換:$<名字>
例如:正則轉換日期格式:
let str = '2019-05-03'; let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;let str1 = str.replace(reg,'$<day>/$<month>/$<year>'); console.log(str);//2019-05-03 console.log(str1);//03/05/2019結合回調函數:
let str = '2019-05-03'; let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;let str1 = str.replace(reg,(...args)=>{// console.log(args);let {year,month,day} = args[args.length-1];return `${day}/${month}/${year}`; }); console.log(str1);//03/05/20197.3dotAll模式(用s)來表示:匹配任意東西
之前,如果用正則匹配任意東西,用‘.’來匹配,但不包括\n,所以之前如果匹配\n之類的東西,是這么寫的
let reg = /^\w+.\w+$/m;//注:在結尾處加m表示多行模式 let str = 'turn-\noff'; console.log(reg.test(str));//true但是如果匹配一些別的文字,比如換行符’\n‘,會匹配失敗
let reg = /^\w+.\w+$/m; let str = 'turn\noff'; console.log(reg.test(str));//false現在可以用dotAll模式來匹配(結尾處加s即可):
let reg = /^\w+.\w+$/s;//加s表示為dotAll模式 let str = 'turn\noff'; console.log(reg.test(str));//true7.3標簽函數
定義:和定義普通函數一樣
function fn(){}調用:
fn();//這樣調用就是普通函數 fn`aaa`;//標簽函數的調用Demo:
function fn(args){return args[0].toUpperCase();//將第一個參數轉為大寫 } console.log(fn`panda`);//調用標簽函數7.4Proxy代理(擴展或增強對象的一些功能)
作用:比如vue中的攔截,預警、上報、擴展功能、統計、增強對象等等;proxy是設計模式的一種,叫做代理模式。
語法:new Proxy(target,handler),target為被代理的對象,handler對代理的對象做什么操作
let obj = {//此對象不暴露給外部name:'jack' }; let newObj = new Proxy(obj,{//此對象是暴露給外部的obj get(target,property){// console.log(target,property);// 在訪問屬性之前做一些操作 console.log(`您訪問了${property}屬性`);return target[property];} } ); console.log(newObj.name);//您訪問了name屬性 jackproxy對象的get(target,property):簡單封裝創建DOM元素的方法:
/* 使用proxy對象簡單封裝創建DOM元素的方法 */ const DOM = new Proxy({},{get(target,property){// console.log(target,property);return function(attr={},...children){// console.log(attr,children);let el = document.createElement(property);for(key of Object.keys(attr)){el.setAttribute(key,attr[key]);}for(child of Object.values(children)){if(typeof child == 'string'){child = document.createTextNode(child);}el.appendChild(child);}return el;}} }); let oDiv = DOM.div({id:'div1'},'我是div','哈哈哈',DOM.a({href:'http://www.baidu.com'},'訪問百度'),DOM.ul({},DOM.li({},'1111'),DOM.li({},'2222'),DOM.li({},'3333'),DOM.li({},'4444')) ); window.onload = function(){document.body.appendChild(oDiv); }proxy對象的set(target,prop,value):檢測設置年齡是否達到要求
let obj = new Proxy({},{set(target,prop,value){// console.log(target,prop,value);if(prop == 'age'){if(!Number.isInteger(value)){throw new TypeError('年齡必須為整數');}if(value>200){throw new RangeError('年齡超標了,必須小于200歲');}}target[prop]=value;} }); obj.a = 123; obj.name = 'pilot'; console.log(obj); obj.age = 201;proxy對象的deleteProperty(target,property):刪除對象屬性之前,顯示提示信息
let json = {a:1,b:2 } let newJson = new Proxy(json,{deleteProperty(target,property){console.log(`您要刪除${property}屬性`);delete target[property];} }); delete newJson.a; console.log(newJson);proxy對象的has(target,property):
let json = {a:1,b:2 } let newJson = new Proxy(json,{has(target,property){console.log(`判斷是否存在調用has方法`);return property in target;} }); console.log('a' in newJson);//true console.log(newJson);proxy對象的apply():
function fn(){return '我是一個函數'; } let newFn = new Proxy(fn,{apply(){return '函數么?';} }); console.log(newFn());apply結合reflect()來使用:
function sum(a,b){return a+b; } let newSum = new Proxy(sum,{apply(target,context,args){// console.log(target,context,args);//console.log(...arguments);// return Reflect.apply(...arguments);//8return Reflect.apply(...arguments)**2;//64 } }); console.log(newSum(3,5));7.5Reflect反射:類似fn.call()、fn.apply()
定義:Reflect.apply(調用的函數,this指向,參數數組)
調用:
// console.log(Math.ceil(5.2));//6 let res = Reflect.apply(Math.ceil,null,[6.8]); console.log(res);//7檢測對象的某一項屬性是否存在:
console.log(Reflect.has(Object,'assign'));//true刪除對象的某一項屬性:
let json = {a:1,b:2}; Reflect.deleteProperty(json,'a'); console.log(json);//{b: 2}---------------------END---------------------
到這也就全部都完了,ES6以及ESNext的一些東西,下面附上其他倆個部分的地址,感謝觀看!
javascript的ES6學習總結(第一部分)
javascript的ES6學習總結(第二部分)
轉載于:https://www.cnblogs.com/abc-x/p/10799583.html
總結
以上是生活随笔為你收集整理的javascript的ES6学习总结(第三部分)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/C++掌握技能(三)
- 下一篇: web项目中关于引入JS/css文件,