摘要:標(biāo)準(zhǔn)入門讀書筆記和命令新增命令,用于聲明變量,是塊級作用域。用于頭部補(bǔ)全,用于尾部補(bǔ)全。函數(shù)調(diào)用的時(shí)候會在內(nèi)存形成一個(gè)調(diào)用記錄,又稱為調(diào)用幀,保存調(diào)用位置和內(nèi)部變量等信息。等到執(zhí)行結(jié)束再返回給,的調(diào)用幀才消失。
《ES6標(biāo)準(zhǔn)入門》讀書筆記
@(StuRep)
let和const命令ES6新增let命令,用于聲明變量,是塊級作用域。
let聲明的變量不會像var聲明的變量發(fā)生“變量提升”現(xiàn)象,所以,變量一定要在聲明后使用,不然就會報(bào)錯(cuò)。
暫時(shí)性死區(qū):只要塊級作用域內(nèi)存在let命令,它所聲明的變量就會“綁定”在這個(gè)區(qū)域,不再受外部的影響。即在代碼塊內(nèi),使用let命令聲明變量之前,這個(gè)變量都是不可用的,這在語法上稱為“暫時(shí)性死區(qū)”。
ES6規(guī)定暫時(shí)性死區(qū)和不存在變量提升,主要是為了減少運(yùn)行時(shí)的錯(cuò)誤,防止在變量聲明前就使用這個(gè)變量,導(dǎo)致意外,這樣的錯(cuò)誤在ES5中很常見。
let不允許在相同作用域內(nèi)重復(fù)聲明同一個(gè)變量。
const命令用來聲明常量,聲明了之后就不能再改變,所以在聲明的時(shí)候就必須賦值,這個(gè)命令同樣是塊級作用域,同樣存在暫時(shí)性死區(qū)。
對于用const聲明的對象,變量名不會指向?qū)ο蟮臄?shù)據(jù),而是指向?qū)ο笏诘牡刂罚杂胏onst聲明的復(fù)合類型變量中的數(shù)據(jù)是可以改變的,這點(diǎn)需要當(dāng)心!
變量的解構(gòu)賦值
解構(gòu):ES6允許按照一定模式,從數(shù)組和對象中提取值,對變量進(jìn)行賦值,這被成為解構(gòu)。如下:
//ES5 var a = 1; var b = 2; var c = 3; //ES6 var [a, b, c] = [1, 2, 3]; //嵌套 let [foo, [[bar], baz]] = [1, [[2], 3]]; foo;//1 bar;//2 baz;//3 //如果等號右邊不是可以遍歷的結(jié)構(gòu),就無法匹配就會報(bào)錯(cuò)。
解構(gòu)賦值是允許設(shè)置默認(rèn)值的,在ES6內(nèi)部使用"==="來判斷一個(gè)位置是否有值。所以,如果一個(gè)數(shù)組成員不嚴(yán)格等于undefined,默認(rèn)值是不會生效的。例如:
[x, y = "b"] = ["a", undefined];//x="a",y="b" [x = 1] = [null];//x=null
默認(rèn)值可以引用解構(gòu)賦值的其他變量,但該變量必須已經(jīng)聲明。例如:
let [x = 1, y = x] = []; //x=1; y=1 let [x = 1, y = x] = [2]; //x=2; y=2 let [x = 1, y = x] = [1, 2]; //x=1; y=2 let [x = y, y = 1] = []; //報(bào)錯(cuò),因?yàn)閤在使用y作為其默認(rèn)值的時(shí)候y還沒有被聲明
對象的解構(gòu)賦值:
var {foo, bar} = {foo: "aaa", bar:"bbb"}; foo //"aaa" bar //"bbb"
對象的解構(gòu)賦值和數(shù)組有一個(gè)重要的不同:數(shù)組的元素是按次序排列的,變量的取值由它的位置來決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。
對象的解構(gòu)賦值可以很方便地將現(xiàn)有對象的方法賦值到某個(gè)變量。例如:
let {log, sin, cos} = Math; //這樣就可以把取對數(shù)、正弦、余弦3個(gè)方法賦值到對應(yīng)的變量上面,用起來很方便;
字符串也可以解構(gòu)賦值,因?yàn)樽址畷晦D(zhuǎn)換成一個(gè)類似數(shù)組的對象。例如:
const [a, b, c, d, e] = "hello"; a // "h" b // "e" c // "l" d // "l" e // "o" let {length : len} = "hello"; len //5
數(shù)值和布爾值的解構(gòu)賦值:解構(gòu)賦值時(shí),如果等號右邊是數(shù)值或布爾值,則會先轉(zhuǎn)為對象。
函數(shù)參數(shù)也可以解構(gòu)賦值,例如:
function add([x,y]){ return x + y; } add([1, 2]) //3
變量的解構(gòu)賦值的用途很多,簡潔易讀:
交換變量的值[x, y] = [y, x];
從函數(shù)返回多個(gè)值;
function example(){ return [1, 2, 3]; } var [a, b, c] = example();
函數(shù)參數(shù)的定義;
//有序 function f([x, y, z]){...}; f([1, 2, 3]); //無序 function f({x, y, z}){...}; f({z:3, y:2, x:1});
提取JSON數(shù)據(jù),可以快速提取json對象中的數(shù)據(jù);
字符串的擴(kuò)展ES6加強(qiáng)了對Unicode的支持,并且擴(kuò)展了字符串對象。
ES5對字符串對象提供了CharAt方法,返回字符串給定位置的字符。但是該方法不能識別碼點(diǎn)大于0xFFFF的字符。于是在ES7中提供了一個(gè)at方法,可以識別Unicode編號大于0xFFFF的字符。
includes(),startsWith(),endsWith()方法。JS中只有indexOf方法可以用來確定一個(gè)字符串是否包含在另一個(gè)字符串中,ES6又提供了三種方法:
includes():返回布爾值,表示是否找到了參數(shù)字符串;
startsWith():返回布爾值,表示參數(shù)字符串是否在源字符串的頭部;
endsWith():返回布爾值,表示參數(shù)字符串是否在源字符串的尾部;
repeat(),repeat方法返回一個(gè)新字符串,表示將原字符串重復(fù)n次。
padStart(),padEnd():ES7推出了字符串補(bǔ)全長度的功能。如果某個(gè)字符串長度未達(dá)指定長度,會在頭部或尾部補(bǔ)全。padStart用于頭部補(bǔ)全,padEnd用于尾部補(bǔ)全。如果原字符串的長度大于或等于指定的最小長度,則返回原字符串。例如:
"x".padStart(5, "ab") //"ababx" "x".padStart(4, "ab") //"abax" "x".padEnd(5, "ab") //"xabab" "x".padEnd(4, "ab") //"xaba" "xxx".padStart(2, "ab") //"xxx"正則的擴(kuò)展
在ES5中,RegExp構(gòu)造函數(shù)只能接受字符串作為參數(shù)var regex = new RegExp("xyz", "i");。在ES6中允許RegExp構(gòu)造函數(shù)接受正則表達(dá)式作為參數(shù),這時(shí)會返回一個(gè)原有正則表達(dá)式的拷貝。
ES6新增了使用大括號表示Unicode字符的表示法,這種表示法在正則表達(dá)式中必須加上u修飾符才能識別。例如:
/u{61}/.test("a"); //false /u{61}/u.test("a"); //true
ES6為正則表達(dá)式新增了flags屬性,會返回正則表達(dá)式的修飾符。ES5的source屬性會返回表達(dá)式的正文。
數(shù)值的擴(kuò)展ES6提供了二進(jìn)制和八進(jìn)制數(shù)值的新寫法,分別用前綴0b(或0B)和0o(或0O)來表示。從ES5開始,在嚴(yán)格模式中,八進(jìn)制數(shù)值就不再允許使用前綴0表示,ES6進(jìn)一步明確,要使用0o前綴表示。
Number.isFinite(),Number.isNaN():ES6在Number對象上面新提供了這兩個(gè)方法,分別用于檢查Infinite(是否非無窮)和NaN這兩個(gè)特殊值。
Number.parseInt(),Number.parseFloat():ES6將全局方法parseInt()和parseFloat()移植到了Number對象上。這樣是為了逐步減少全局性的方法,使語言逐步模塊化。
//ES5 parseInt(""); //ES6 Number.parseInt(""); Number.parseInt === parseInt; //true
Number.isInteger():該方法用來判斷一個(gè)值是否為整數(shù)。
新增了一個(gè)極小的常量Number.EPSILON,當(dāng)我們做計(jì)算的時(shí)候,如果誤差可以小于這個(gè)常量,那么就可以認(rèn)為計(jì)算的結(jié)果是正確的。
Number.isSafeInteger():JavaScript能夠準(zhǔn)確表示的整數(shù)范圍在-2{53}到2{53}之間,超出的就不能精確表示了,該函數(shù)用來判斷一個(gè)數(shù)是否落在這個(gè)范圍之內(nèi)。
Math對象的擴(kuò)展,ES6在Math對象上新增了17個(gè)與數(shù)學(xué)相關(guān)的方法:
Math.trunc():用于去除小數(shù)部分,返回整數(shù)部分;
Math.sign():用于判斷一個(gè)數(shù)到底是正數(shù)、負(fù)數(shù)還是0,整數(shù)返回1,負(fù)數(shù)返回-1,0返回0,-0返回-0,其他返回NaN;
Math.cbrt():計(jì)算一個(gè)數(shù)的立方根;
Math.clz32():返回一個(gè)數(shù)的32位無符號數(shù)有多少個(gè)前導(dǎo)0;
Math.imul():返回兩個(gè)數(shù)以32位帶符號整數(shù)形式相乘的結(jié)果,返回的也是一個(gè)帶符號整數(shù),例如:Math.imul(-1, 8); //-8
Math.fround():返回一個(gè)數(shù)的單精度浮點(diǎn)數(shù)形式;
Math.hypot():返回所有參數(shù)平方和的平方根,例如:Math.hypot(3, 4);//5
還有一些和對數(shù)運(yùn)算、三角函數(shù)運(yùn)算、指數(shù)運(yùn)算相關(guān)的方法。
數(shù)組的擴(kuò)展Array.from():將類似數(shù)組的對象和可遍歷的對象轉(zhuǎn)為真正的數(shù)組;
Array.of():將一組數(shù)值轉(zhuǎn)換為數(shù)組,例如:Array.of(3, 11, 8) //[3,11,8]
fill()方法,使用給定值填充數(shù)組,例如:new Array(3).fill(7) //[7,7,7]
數(shù)組實(shí)例的entries()、keys()、和values()方法,主要用來遍歷數(shù)組,keys()是對鍵名的遍歷,values()是對鍵值的遍歷,entries()是對鍵值對的遍歷;
函數(shù)的擴(kuò)展ES6之前不能直接為函數(shù)的參數(shù)指定默認(rèn)值,所以經(jīng)常有x = x || "XXX"這樣的寫法,ES6允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,就可以這樣寫function test(x, y = "xxx"){};,這樣的設(shè)計(jì)還有一個(gè)好處就是開發(fā)人員閱讀別人的代碼一眼就能看出來在調(diào)用這個(gè)接口哪些參數(shù)是可省的。此外,這種寫法還可以和解構(gòu)賦值結(jié)合使用,非常靈活。
函數(shù)的length屬性修改,如果函數(shù)中的參數(shù)有指定默認(rèn)值,那么length就不會把這個(gè)參數(shù)計(jì)算進(jìn)去,例如:(function(a=5){}).length;//0
作用域問題,如果一個(gè)參數(shù)的默認(rèn)值是一個(gè)變量,那么這個(gè)變量所處的作用域與其他變量的作用域規(guī)則是一樣的,先是當(dāng)前函數(shù)的作用域,然后才是全局作用域;
ES6引入了rest參數(shù)(形式為"...變量名"),用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對象了。rest參數(shù)搭配的變量是一個(gè)數(shù)組,該變量將多余的參數(shù)放入其中,例如:
function add(...values){ let sum = 0; for(var val of values){ sum += val; } return sum; } add(2, 5, 3); //10 //add函數(shù)是一個(gè)求和函數(shù),利用rest參數(shù)可以向該函數(shù)傳入任意數(shù)目的參數(shù)。
擴(kuò)展運(yùn)算符,三個(gè)點(diǎn)(...),作用是把一個(gè)數(shù)組轉(zhuǎn)為用逗號隔開的參數(shù)序列。例如:console.log(1,...[2,3,4],5);//1 2 3 4 5;
擴(kuò)展運(yùn)算符替代數(shù)組的apply方法,擴(kuò)展運(yùn)算符可以直接把數(shù)組拆開,例如:
//ES5 function f(x,y,z){}; var args = [0,1,2]; f.apply(null, args); //ES6 function f(x,y,z){}; var args = [0,1,2]; f(...args);
擴(kuò)展運(yùn)算符提供了數(shù)組合并的新方法:
//ES5 [1,2].concat(more) //ES6 [1,2, ...more]
擴(kuò)展運(yùn)算符還可以與解構(gòu)賦值結(jié)合;
ES6還寫入了函數(shù)的name屬性,可以返回函數(shù)名,雖然這個(gè)屬性很早就被各個(gè)瀏覽器支持了,但是在ES6才正式寫入;
箭頭函數(shù):ES6允許使用"箭頭"(=>)定義函數(shù),例如:
var sum = (num1, num2) => num1 + num2; //等價(jià)于 var sum = function(num1, num2){ return num1 + num2; }
使用箭頭函數(shù)有幾個(gè)注意點(diǎn):
函數(shù)體內(nèi)的this對象就是定義時(shí)所在的對象,而不是使用時(shí)所在的對象。在js中this的指向是可以改變的,但是在箭頭函數(shù)中this的指向是不變的;
不可以當(dāng)作構(gòu)造函數(shù)。也就是說,不可以使用new命令;
不可以使用arguments對象,該對象在函數(shù)體內(nèi)不存在。如果要用,可以用ES6中的rest參數(shù)代替;
不可以使用yield命令,因此箭頭函數(shù)不能用作Generator函數(shù);
函數(shù)綁定:在ES6之后的ES7版本中有一個(gè)提案是函數(shù)綁定運(yùn)算符(::),雙冒號左邊是一個(gè)對象,右邊是一個(gè)函數(shù)。這個(gè)運(yùn)算符會自動將左邊的對象作為this綁定到右邊的函數(shù)上面,例如:foo::bar(...arguments)等價(jià)于bar.apply(foo,arguments;)。感覺函數(shù)綁定這個(gè)設(shè)計(jì)非常的便捷,不需要在顯式的去綁定一下上下文,期待該提案的通過(目前babel已經(jīng)支持這個(gè)寫法了);
尾調(diào)用:就是指某個(gè)函數(shù)的最后一步是調(diào)用另一個(gè)函數(shù);
尾調(diào)用優(yōu)化:尾調(diào)用之所以與其他調(diào)用不同,就在于其特殊的調(diào)用位置。函數(shù)調(diào)用的時(shí)候會在內(nèi)存形成一個(gè)‘調(diào)用記錄’,又稱為‘調(diào)用幀’,保存調(diào)用位置和內(nèi)部變量等信息。如果在函數(shù)A內(nèi)部調(diào)用函數(shù)B,那么在A的調(diào)用幀上方還會形成一個(gè)B的調(diào)用幀。等到B執(zhí)行結(jié)束再返回給A,B的調(diào)用幀才消失。如果B的內(nèi)部調(diào)用了C,那么還會產(chǎn)生一個(gè)調(diào)用幀,以此類推,所有調(diào)用幀會形成一個(gè)‘調(diào)用棧’。然而尾調(diào)用是函數(shù)的最后一步操作,所以不需要保留外層函數(shù)的調(diào)用幀,因?yàn)檎{(diào)用位置、內(nèi)部變量等信息都不會再用到了,直接用內(nèi)層函數(shù)的調(diào)用幀取代外層函數(shù)的即可;
尾遞歸:函數(shù)調(diào)用自身稱為遞歸,如果尾調(diào)用自身就稱為尾遞歸。遞歸非常耗費(fèi)內(nèi)存,因?yàn)樾枰瑫r(shí)保存成千上百個(gè)調(diào)用幀,很容易stackoverflow。但對于尾遞歸來說,只存在一個(gè)調(diào)用幀,所以永遠(yuǎn)不會發(fā)生“棧溢出”錯(cuò)誤。例如:
//這是一個(gè)階乘函數(shù),計(jì)算n的階乘,最多需要保存n個(gè)調(diào)用記錄,復(fù)雜度為O(n)。 function factorial(n){ if(n === 1) return 1; return n * factorial(n - 1); } //改寫成尾遞歸,只保用一個(gè)調(diào)用記錄,則復(fù)雜度為O(1); function factorial(n, totla){ if(n === 1) return total; return factorial(n - 1, n * total); }
由此可見‘尾調(diào)用優(yōu)化’對于遞歸操作的意義非常重大,所以一些函數(shù)式編程語言將其寫入了語言規(guī)格。ES6也是如此,第一次明確規(guī)定,所有ECMAScript的實(shí)現(xiàn),都必須部署‘尾調(diào)用優(yōu)化’。這就是說,在ES6中,只要使用尾遞歸,就不會棧溢出,節(jié)省內(nèi)存。
(未完待續(xù)......)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/79861.html
摘要:阮一峰老師開源作品。書上的示例代碼可以通過在線網(wǎng)站代碼調(diào)試工具調(diào)試。 阮一峰老師開源作品。 書上的示例代碼可以通過 在線網(wǎng)站代碼調(diào)試工具 JS Bin 調(diào)試。 作用域 作用域鏈 每個(gè)變量或函數(shù)通過執(zhí)行環(huán)境 (execution context) 定義了其有權(quán)訪問的其他數(shù)據(jù),決定了他們各自的行為; 全局執(zhí)行環(huán)境是最頂層的執(zhí)行環(huán)境,根據(jù)宿主環(huán)境的不同,表示全局執(zhí)行環(huán)境的對象也不同:在瀏覽...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個(gè)方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細(xì)介紹 HTT...
摘要:于是我就先把這本薄的經(jīng)典書語言精粹修訂版豆瓣讀書本書簡介總共章,除去附錄,才頁,讀完并記錄了一些筆記。讀書筆記還可以分享給別人看。編程語言第版定義了的標(biāo)準(zhǔn)。程序檢查時(shí)丟棄值為函數(shù)的屬性。 之前看到這篇文章,前端網(wǎng)老姚淺談:怎么學(xué)JavaScript?,說到怎么學(xué)習(xí)JavaScript,那就是看書、分析源碼。10本書讀2遍的好處,應(yīng)該大于一本書讀20遍。看書主動學(xué)習(xí),看視頻是被動學(xué)習(xí)。看...
摘要:原文地址一個(gè)非常適合入門學(xué)習(xí)的博客項(xiàng)目前端掘金一個(gè)非常適合入門學(xué)習(xí)的項(xiàng)目,代碼清晰結(jié)構(gòu)合理新聞前端掘金介紹一個(gè)由編寫的新聞。深入淺出讀書筆記知乎專欄前端專欄前端掘金去年的一篇老文章,恰好今天專欄開通,遷移過來。 破解前端面試(80% 應(yīng)聘者不及格系列):從閉包說起 - 掘金修訂說明:發(fā)布《80% 應(yīng)聘者都不及格的 JS 面試題》之后,全網(wǎng)閱讀量超過 6W,在知乎、掘金、cnodejs ...
摘要:原文地址一個(gè)非常適合入門學(xué)習(xí)的博客項(xiàng)目前端掘金一個(gè)非常適合入門學(xué)習(xí)的項(xiàng)目,代碼清晰結(jié)構(gòu)合理新聞前端掘金介紹一個(gè)由編寫的新聞。深入淺出讀書筆記知乎專欄前端專欄前端掘金去年的一篇老文章,恰好今天專欄開通,遷移過來。 破解前端面試(80% 應(yīng)聘者不及格系列):從閉包說起 - 掘金修訂說明:發(fā)布《80% 應(yīng)聘者都不及格的 JS 面試題》之后,全網(wǎng)閱讀量超過 6W,在知乎、掘金、cnodejs ...
閱讀 1892·2021-11-23 09:51
閱讀 1535·2021-11-19 09:40
閱讀 3208·2021-11-11 11:01
閱讀 1105·2021-09-27 13:34
閱讀 1835·2021-09-22 15:56
閱讀 2122·2019-08-30 15:52
閱讀 1061·2019-08-30 14:13
閱讀 3473·2019-08-30 14:10