ES6入門之變數的解構賦值(二)
前言
在上一章 ES6入門之let和const命令中我們對ES6的相關語法已經有了初步瞭解,上一章中我們主要學習了三大部分的內容,let命令的使用,塊級作用域,const命令的使用,那麼從本篇部落格將進一步深入瞭解ES6中的相關語法,畢竟未來ES6是主流。
本章目標
- 學會陣列的解構賦值
- 學會物件的解構賦值
- 學會字串的解構賦值
- 學會數值和布林值的解構賦值
- 學會函式引數的解構賦值
- 學會解構賦值的用途
本人對解構賦值的理解:模式匹配,匹配成功獲取值,匹配不成功則為undefined,好比開心消消樂一樣(我沒有玩過,但是聽過一點點),開心消消樂中只要有相同的就會消失,然後加分,而模式匹配呢?匹配成功加分,匹配不成功則失敗。
陣列的解構賦值
陣列的解構賦值十分簡單,只要等號左右兩邊模式匹配成功,則獲取值,否則為undefined,在講解陣列解構賦值之前,我們先來看下我們以前定義變數的格式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script type="text/javascript"> let a=1; let b=2; let c=3; //或者 let a=3, b=4, c=5; //ES6的模式 let [a,b,c]=[4,5,6];//左右兩邊相等,a=4,b=5,c=6 </script> </body> </html>
在這裡我們已經使用了陣列的解構賦值,即let [a,b,c]=[4,5,6]左右兩邊進行模式匹配,可得a=4,b=5,c=6
(1)不完全解構
解構除了完全解構之外,還具備不完全解構的特性,即左邊的模式只匹配一部分等號右邊的陣列
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script type="text/javascript"> let [x,y]=[1,2,3]; console.log(x);//1 console.log(y);//2 let [a,[b],d]=[1,[2,3],4]; console.log(a);//1 console.log(b);//2 console.log(d);//4 </script> </body> </html>
(2)特殊值
如果等號右邊不是陣列,那麼將會報錯
let [foo] = 1; let [foo] = false; let [foo] = NaN; let [foo] = undefined; let [foo] = null;
(3)預設值
陣列的解構允許有預設值,如果一個數組的成員為null,預設值就不會生效,因為null不嚴格等於undefined
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script type="text/javascript"> let [foo=true]=[]; console.log(foo);//true let [x,y='b']=['a']; let [z,w='b']=['a',undefined]; console.log(x);//a console.log(y);//b console.log(z);//a console.log(w);//b let [a=1]=[undefined]; let [b=2]=[null]; console.log(a);//1 console.log(b);//null </script> </body> </html>
物件的解構賦值
關於物件的解構賦值我總結了如下三點
- 陣列的元素是按次序排列的,變數的取值有它的位置決定,而物件的屬性是沒有次序的,變數必須和屬性同名,才能取到正確的值
- 如果解構失敗,變數的值等於undefined
- 物件解構賦值的內部機制,是先找到同名屬性,然後再賦給對應的變數,真正被賦值的是後者,而不是前者
示例1
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>物件的解構賦值</title> </head> <body> <script type="text/javascript"> //按順序排列 // let {foo,bar}={foo:'foo',bar:'bar'}; // console.log(foo);//foo // console.log(bar);;//bar //不按順序排列 // let {bar,foo}={foo:'foo',bar:'bar'}; // console.log(bar);//bar // console.log(foo);;//foo //解構不成功,值為undefined let {baz}={foo:'foo',bar:'bar'}; console.log(baz);//undefined </script> </body> </html>
在這個案例中,我們有按順序的解構,沒有順序的解構,以及解構不成功的情況
示例二
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>物件的解構賦值</title> </head> <body> <script type="text/javascript"> let {foo:baz}={foo:'aaa',bar:'bbb'} console.log(baz);//aaa let obj={first:'hello',last:'world'}; let {first:a,last:b}=obj; console.log(a);//hello console.log(b);//world </script> </body> </html>
從而可以看出:物件解構賦值的原理是先找到同名屬性,然後再賦給對應變數,真正被賦值的是後者而不是前者
字串的解構賦值
字串的結構賦值十分簡單,和之前的解構賦值一樣也是模式匹配,注意:字串中有length屬性
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>字串解構賦值</title> </head> <body> <script type="text/javascript"> const [a,b,c,d,e]='hello'; console.log(a);;//h console.log(b);//e console.log(c);//l console.log(d);//l console.log(e);//o let {length:len}='hello'; console.log(len);//5 </script> </body> </html>
數值和布林值的解構賦值
解構賦值原理:只要等號右邊的值不是陣列或物件,就先將其轉為物件,但是也有特殊情況,如:undefined和null無法轉為物件,所以對它們進行解構賦值都會報錯。這一點非常重要
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>數值和布林值的解構賦值</title> </head> <body> <script type="text/javascript"> // let {toString:s}=123; // console.log(s===Number.prototype.toString); // let {toString:b}=true; // console.log(b===Boolean.prototype.toString); let {prototype:x}=undefined; let {prop:y}=null; console.log(x);//報錯 console.log(y);//報錯 </script> </body> </html>
函式引數的解構賦值
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>函式引數解構賦值</title> </head> <body> <script type="text/javascript"> function add([x,y]){ return x+y; } console.log(add([1,3]));//4 [[1,2],[3,4]].map(([a,b])=>{ console.log(a+b);//4,7 }) //使用預設值 function move({x=0,y=0}){ return [x,y] } move({x:3,y:10});//[3,8] move({x:3})//[3,0] move({})//[0,0] move();//[0,0] function bar({x,y}={x:0,y=0}){ return [x,y] } move({x:3,y:8});//[3,8] move({x:3});//[3,undefined] move({});//[undefined,undefined] move();//[0,0] </script> </body> </html>
在move方法中函式move
的引數是一個物件,通過對這個物件進行解構,得到變數x
和y
的值。如果解構失敗,x
和y
等於預設值,而函式bar的引數指定預設值,而不是為變數x
和y
指定預設值,所以會得到與前一種寫法不同的結果
解構賦值的實際用途
(1)交換變數的值
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>解構賦值的用途</title> </head> <body> <script type="text/javascript"> //(1)交換變數的值 let x=1; let y=2; [x,y]=[y,x]; console.log(x);//2 console.log(y);//1 </script> </body> </html>
在這裡,我們可以看到x和y的值進行了交換,x的值從1變成的2,而y的值從2變成了1
(2)從函式返回多個值
我們知道javascript中中使用return只能返回一個值,如果需要返回多個值的話就需要將資料放在陣列或物件中,然後return回去,但是有了解構賦值,你想要取出這些值就非常方便,我們看下下面的示例。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>解構賦值的用途</title> </head> <body> <script type="text/javascript"> //(2)從函式返回多個值 //返回一個數組 function bar(){ return[1,2,3] } let[a,b,c]=bar(); console.log(a);//1 console.log(b);//2 console.log(c);//3 //返回一個物件 function baz(){ return{ x:1, y:2, } } let {x,y}=baz(); console.log(x);//1 console.log(y);//2 </script> </body> </html>
在這裡我們返回一個數組之後使用a,b,c進行解構賦值,匹配a=1,b=2,c=3,而返回物件之後我們使用物件來接收,注意:返回物件的鍵名一定要和需要解構的鍵名一致,否則取到的值為undefined
(3)函式引數定義
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>解構賦值的用途</title> </head> <body> <script type="text/javascript"> //(3)函式引數定義 //引數是一組有次序的值 function foo([x,y,z]){ console.log(x);//1 console.log(y);//2 console.log(z);//3 } foo([1,2,3]); //引數是一組無序的值 function bar({x,y,z}){ console.log(x);//10 console.log(y);//20 console.log(z);//1 } bar({z:1,x:10,y:20}) </script> </body> </html>
(4)提取JSON資料
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>解構賦值的用途</title> </head> <body> <script type="text/javascript"> //(4)提取JSON資料 let stu={ name:'一隻流浪的kk', age:18, sex:'male' } let {name:name,age:age,sex:sex}=stu; console.log(name,age,sex);//一隻流浪的kk,18,male </script> </body> </html>
使用解構賦值可以很方便的提取JSON中的資料
(5)函式引數預設值
這種方法我們見過很多,再封裝ajax的時候經常用到或者是擴張jquery外掛的時候,我們都會新增預設值
//(5)函式引數預設值 ; (function(method) { method(window, window.document, jQuery); }(function(win, doc, $) { $.fn.SuperPlus = function(options) { //預設引數 var setting={ length:3, color:"blue" }; //使用使用者的引數覆蓋預設引數 $.extend(setting,options); return $.each(this, function(index, obj) { $("<span/>").html("+").css("cursor", "pointer").css("color",setting.color).click(function() { $(obj).width($(obj).width() + setting.length); }).insertAfter(obj); }); } }));
在這裡我們就是指定了預設值,我們對外開發我們可以讓使用者進行修改的一些引數,當用戶沒有傳遞的時候,我們就使用預設值
(6)遍歷Map結構
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>解構賦值的用途</title> </head> <body> <script type="text/javascript"> //(6)遍歷Map結構 const map=new Map(); map.set('first','hello'); map.set('last','world'); for(let [key,value] of map){ console.log('鍵是:'+key,'值是:'+value);//鍵:first,last,值:hello,world } //或者 for(let [key,value] of map.entries()){ console.log('鍵是:'+key,'值是:'+value);//鍵:first,last,值:hello,world } //如果只想遍歷key for(let [key,] of map){ console.log(key);//first,last } //如果只想遍歷value for(let [,value] of map){ console.log(value);//hello,world } </script> </body> </html>
這裡涉及到map的相關知識,關於ES6新增的資料結構,檢視部落格 https://www.cnblogs.com/jjgw/p/11561169.html
(7)輸入模組的指定方法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>解構賦值的用途</title> </head> <body> <script type="text/javascript"> //(7)輸入模組的指定方法 const{add,sub}=require('count'); </script> </body> </html>
這種方法我們之後會用到,關於ES6中模組的載入,例如:AMD,CMD,UMD等等,現階段只需要瞭解一下
&n