摘要:正式因為它沒有,所以也就不能用作構(gòu)造函數(shù)。函數(shù)的最后一步是調(diào)用函數(shù),這就叫尾調(diào)用尾遞歸函數(shù)調(diào)用自身,稱為遞歸。它的參數(shù)是一個回調(diào)函數(shù),所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù),直到找出第一個返回值為的成員,然后返回該成員。
這是ES6的入門篇教程的筆記,網(wǎng)址:鏈接描述,以下內(nèi)容中粗體+斜體表示大標(biāo)題,粗體是小標(biāo)題,還有一些重點;斜體表示對于自身,還需要下功夫?qū)W習(xí)的內(nèi)容。這里面有一些自己的見解,所以若是發(fā)現(xiàn)問題,歡迎指出~
上一篇es5的到最后令人崩潰,看來深層的東西還是不太熟,希望這次不要這樣了?。?!
函數(shù)的擴(kuò)展
1、函數(shù)參數(shù)的默認(rèn)值
基本用法
ES6之前,不能直接為函數(shù)的參數(shù)指定默認(rèn)值,只能采用變通的方法。
參數(shù)默認(rèn)值不是傳值的,而是每次都重新計算默認(rèn)值表達(dá)式的值。也就是說,參數(shù)默認(rèn)值是惰性求值的。
function log(x, y) { y = y || "World"; console.log(x, y); } log("Hello", "") // Hello World 后一個字段是本意是空字符,也會被賦值為"World" // 改進(jìn)一下,賦值時為以下 if (typeof y === "undefined") { y = "World"; } // ES6允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面 function log(x, y = "World") { console.log(x, y); } log("Hello") // Hello World log("Hello", "China") // Hello World log("Hello", "") // Hello let x = 99; function foo(p = x + 1) { console.log(p); } foo() // 100 x = 100; foo() // 101 這就是惰性求值,參數(shù)p的默認(rèn)值是x+1,每次調(diào)用函數(shù)foo,都會重新計算x + 1,而不是默認(rèn)p等于100
與解構(gòu)賦值默認(rèn)值結(jié)合使用
參數(shù)默認(rèn)值可以與解構(gòu)賦值的默認(rèn)值,結(jié)合起來使用。
function foo({x, y = 5}) { // 只用了對象的結(jié)構(gòu)賦值默認(rèn)值,沒有使用函數(shù)參數(shù)的默認(rèn)值。 console.log(x, y); } foo({}) // undefined 5 foo() // TypeError: Cannot read prototype "x" of undefined function foo({x, y = 5} = {}) { // 如果沒有提供參數(shù),函數(shù)foo的參數(shù)默認(rèn)為一個空對象。 console.log(x, y); } foo() // undefined 5
有點要繞暈了,下面這個是重點,如果能知道兩者的區(qū)別,說明就已經(jīng)理解了。
// 第一種 function m1({x = 0, y = 0} = {}) { return [x, y]; } // 第二種 function m2({x, y} = {x: 0, y: 0}) { return [x, y]; }
上面的這兩種寫法都對函數(shù)的參數(shù)設(shè)定了默認(rèn)值,區(qū)別在于第一種行數(shù)參數(shù)的默認(rèn)值是空對象,但是這是了對象解構(gòu)賦值的默認(rèn)值;第二種函數(shù)參數(shù)的默認(rèn)值是一個有具體屬性的對象,但是沒有設(shè)置對象解構(gòu)賦值的默認(rèn)值。
一起看看它們的輸出情況。
// 函數(shù)沒有參數(shù)的情況 m1() // [0, 0] m2() // [0, 0] // x有值,y無值的情況 m1({x: 3}) // [3, 0] m2({x: 3}) // [3, undefined] // x和y都無值的情況 m1({}) // [0, 0] m2({}) // [undefined, undefined] // 綜上,推薦第一種寫法,當(dāng)然按需寫更好
參數(shù)默認(rèn)值的位置
通常情況下,定義了默認(rèn)值的參數(shù),應(yīng)該是函數(shù)的尾參數(shù)。因為這樣比較容易看出來,到底省略了那些參數(shù)。如果非尾部的參數(shù)設(shè)置默認(rèn)值,實際上這個參數(shù)是沒法省略的,除非顯式輸入undefined。
// function f(x = 1, y) { return [x, y]; } f() // [1, undefined] f(2) // [2, undefined] f(, 1) // 報錯 f(undefined, 1) // [1, 1]
作用域
一旦設(shè)置了參數(shù)的默認(rèn)值,函數(shù)進(jìn)行聲明初始化時,參數(shù)會形成一個多帶帶的作用域(context)。等到初始化結(jié)束,這個作用域就會消失。這種語法行為,再不設(shè)置參數(shù)默認(rèn)值時,是不會出現(xiàn)的。
let x = 1; function f(y = x) { // 參數(shù)y = x形成一個多帶帶的作用域,在這個作用域里面,變量x本身沒有定義,所以指向外層的全局變量x let x = 2; // 函數(shù)調(diào)用時,函數(shù)體內(nèi)部的局部變量x影響不到默認(rèn)值變量x console.log(y) } f() // 1 // 如果此時,全局變量x不存在,就會報錯 function f(y = x) { let x = 2; console.log(y); } f() // ReferenceError: x is not defined
2、rest參數(shù)
ES6引入rest參數(shù)(形式為...變量名),用于獲取函數(shù)的多余參數(shù),這樣就不需要arguments對象了。rest參數(shù)搭配的變量時一個數(shù)組,該變量將多余的參數(shù)放入數(shù)組中。
注:rest參數(shù)之后不能再有其他參數(shù)(即只能是最后一個參數(shù)),否則會報錯。
函數(shù)的length屬性,不包括rest參數(shù)。
function add(...values) { // 利用rest參數(shù),可以向該函數(shù)傳入任意數(shù)目的參數(shù) let sum = 0; for(let val of values) { sum += val; } return sum; } add(2, 5, 3) // 10 // 利用rest參數(shù)改寫數(shù)組push方法 function push(array, ...items) { items.forEach(function(item) { array.push(item); console.log(item); }) } let a = []; push(a, 1, 2, 3); // rest參數(shù)之后不能再有其他參數(shù) // 報錯 function f(a, ...b, c) { // ... }
5、箭頭函數(shù)
基本用法
ES6允許使用“箭頭”(=>)定義函數(shù)。
如果箭頭函數(shù)不需要參數(shù)或需要多個參數(shù),就使用一個圓括號代表參數(shù)部分。
如果箭頭函數(shù)的代碼塊部分多于一條語句,就要使用大括號將它們括起來,并且使用return語句返回。
注:函數(shù)體內(nèi)的this對象,就是定義時所在的對象,而不是使用時所在的對象(this對象的指向是可變的,但是在箭頭函數(shù)中,它是固定的);不可以當(dāng)作構(gòu)造函數(shù),也就是說,不可以使用new命令,否則會拋出一個錯誤。
let f = v => v; // 等同于 let f = function (v) { return v; }; let f = () => 5; // 等同于 let f = function () { return 5 }; let sum = (num1, num2) => num1 + num2; // 等同于 let sum = function(num1, num2) { return num1 + num2; }; // 報錯 返回對象必須在對象外面加上括號,否則會報錯。 let getItem = id => { id: id, name: "Temp" }; // 不報錯 let getItem = id => ({ id: id, name: "Temp" }); // 箭頭函數(shù)可以與變量解構(gòu)結(jié)合使用 const full = ({ first, last }) => first + "" + last; // 箭頭函數(shù)使得表達(dá)更加簡介 const isEven = n => n % 2 === 0; const aqure = n => n * n; // 簡化回調(diào)函數(shù) let result = values.sort((a, b) => a-b); // 正常寫法 let result = values.sort(function (a, b) { return a - b; });
需要注意this的指向問題:箭頭函數(shù)讓this指向固定化,箭頭函數(shù)的this綁定定義時錯在的作用域,普通函數(shù)的this指向運(yùn)行時所在的作用域。
let handle = { id: "123456", init: function() { document.addEventListener("click", event => this.doSomething(event.type), false); // 箭頭函數(shù),this.doSomething中的this指向handler對象(定義時的作用域);否則的話,this指向document對象 }, doSomething: function(type) { console.log("Handling " + type + " for " + this.id); } };
this指向的固定化,并不是因為箭頭函數(shù)內(nèi)部有綁定this的機(jī)制,實際原因是箭頭函數(shù)根本沒有自己的this,導(dǎo)致內(nèi)部的this就是外層代碼塊的this。正式因為它沒有this,所以也就不能用作構(gòu)造函數(shù)。
// ES6 function foo() { setTimeout(() => { console.log("id:", this.id); }, 100); } // ES5 function foo() { let _this = this; setTimeout(function () { console.log("id:", _this.id); }, 100); }
箭頭函數(shù)不適用場合
1、定義對象的方法,且該方法內(nèi)部包括this。
這是因為對象不構(gòu)成多帶帶的作用域,導(dǎo)致箭頭函數(shù)定義時的對象就是全局作用域。
const cat = { lives: 9, jumps: () => { // 箭頭函數(shù),使得this指向全局對象,不會得到預(yù)期解構(gòu);如果是普通函數(shù),該方法內(nèi)部的this指向cat this.lives--; } }
2、需要動態(tài)this的時候,也不應(yīng)使用箭頭函數(shù)。
let button = document.getElementById("press"); button.addEventListener("click", () => { this.classList.toggle("on"); });
點擊按鈕會報錯,因為button的監(jiān)聽函數(shù)是一個箭頭函數(shù),導(dǎo)致里面的this就是全局對象。如果改成普通函數(shù),this就會動態(tài)指向被點擊的按鈕對象。
另外,如果函數(shù)體很復(fù)雜,有很多行,或者函數(shù)內(nèi)部有大量的讀寫操作,不單純是為了計算值,這時也不應(yīng)該使用箭頭函數(shù),而是要使用普通函數(shù),這樣可以提高代碼可讀性。
6、尾調(diào)用優(yōu)化
尾調(diào)用(Tail Call)是函數(shù)式編程的一個重要概念,本身非常簡單,一句話就能說清楚,就是指某個函數(shù)的最后一步是調(diào)用另一個函數(shù)。
function f(x) { return g(x); // 函數(shù)f的最后一步是調(diào)用函數(shù)g,這就叫尾調(diào)用 }
尾遞歸
函數(shù)調(diào)用自身,稱為遞歸。如果尾調(diào)用自身,就稱為尾遞歸。
數(shù)組的擴(kuò)展
含義
擴(kuò)展運(yùn)算符(spread)是三個點(...)。它好比rest參數(shù)的逆運(yùn)算,將一個數(shù)組轉(zhuǎn)為用逗號分隔的參數(shù)序列。
console.log(1, ...[2, 3, 4], 5); // 1 2 3 4 5 // 如果擴(kuò)展運(yùn)算符后面是一個空數(shù)組,則不產(chǎn)生任何效果 [...[], 1] // [1] // 注意,只有函數(shù)調(diào)用時,擴(kuò)展運(yùn)算符才可以放在圓括號中,否則會報錯。前兩種報錯,是因為擴(kuò)展運(yùn)算符所在的括號不是函數(shù)調(diào)用。 (...[1, 2]) // Uncaught SyntaxError: Unexpected token ... console.log((...[1, 2])) // Uncaught SynaxError: Unexpexted token ... console.log(...[1, 2]) // 1 2
擴(kuò)展運(yùn)算符的應(yīng)用
(1)復(fù)制數(shù)組
數(shù)組是復(fù)合的數(shù)據(jù)類型,直接復(fù)制的話,指數(shù)復(fù)制了指向底層數(shù)據(jù)結(jié)構(gòu)的指針,而不是克隆一個全新的數(shù)組。
const a1 = [1, 2]; const a2 = a1; // a2并不是a1的克隆,而是指向同一份數(shù)據(jù)的另一個指針,修改a2,會直接導(dǎo)致a1的改變。 a2[0] = 2; a1; // [2, 2] // ES5復(fù)制數(shù)組 const a1 = [1, 2]; const a2 = a1.concat(); a2[0] = 2; a1 // [1, 2] // ES6的簡便寫法 const a1 = [1, 2]; const a2 = [...a1]; const [...a2] = a1; // 這兩種寫法,a2都是a1的克隆
(2)合并數(shù)組
擴(kuò)展運(yùn)算符提供了數(shù)組合并的新寫法。
const arr1 = ["a", "b"]; const arr2 = ["c"]; // ES5的合并數(shù)組 arr1.concat(arr1, arr2); // ES6的合并數(shù)組 [...arr1, ...arr2]; // 注意下面的合并,數(shù)組里面的元素是對象,拷貝過去的就只能是地址?。?! const a1 = [{ foo: 1 }]; const a2 = [{ bar: 2 }]; const a3 = a1.concat(a2); const a4 = [...a1, ... a2]; a3[0] === a1[0]; // true a4[0] === a1[0]; // true // 拷貝過去的只有地址,也就是說,如果修改了原數(shù)組的成員,會同步反映到新數(shù)組。
(3)與解構(gòu)賦值結(jié)合
擴(kuò)展運(yùn)算符可以與解構(gòu)賦值結(jié)合起來,用于生成數(shù)組。
// ES5 a = list[0], rest = list.slice(1) // ES6 [a, ...rest] = list // 如果將擴(kuò)展運(yùn)算符用于數(shù)組賦值,只能放在參數(shù)的最后一位,否則會報錯 // 報錯 const [...butLast, last] = [1, 2, 3, 4, 5];
(4)字符串
擴(kuò)展運(yùn)算符還可以將字符串轉(zhuǎn)為真正的數(shù)組。
[..."hello"]; // ["h", "e", "l", "l", "o"]
5、數(shù)組實例的find()和findIndex()
數(shù)組實例的find方法,用于找出第一個符合條件的數(shù)組成員。它的參數(shù)是一個回調(diào)函數(shù),所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù),直到找出第一個返回值為true的成員,然后返回該成員。如果沒有符合條件的成員,則返回undefined。接受三個參數(shù),依次為當(dāng)前的值、當(dāng)前的位置和原數(shù)組。
[1, 4, -5, 10].find((n) => n < 0) // -5
數(shù)組實例的findIndex方法的用法與find方法非常類似,返回第一個符合條件的數(shù)組成員的位置,如果所有成員都不符合條件,則返回-1.
7、數(shù)組實例的entries(),keys()和values()
ES6提供三個新的方法——entries(), keys()和values()——用于遍歷數(shù)組。keys()是對鍵名的遍歷、values()是對鍵值的遍歷,entries()是對鍵值對的遍歷。
感覺可以用foreach一步做到,沒必要細(xì)看。。。。
8、數(shù)組實例的includes()
Array.prototype.includes方法返回一個布爾值,表示某個數(shù)組是否包含給定的值,與字符串的includes方法類似。ES2016引入了該方法。
[1, 2, 3].includes(2) // true [1, 2, 3].includes(4) // false [1, 2, NaN].includes(NaN) // true [1, 2, 3].includes(3, 3); // false 第二個參數(shù)表示搜索的起始位置 [1, 2, 3].includes(3, -1); //true
9、數(shù)組實例的flat(),flatMap()
數(shù)組的成員有時還是數(shù)組,Array.prototype.flat()用于將嵌套的數(shù)組“拉平”,變成一維的數(shù)組。該方法返回一個新數(shù)組,對原數(shù)據(jù)沒有影響。
[1, 2, [3, [4, 5]]].flat(); // [1, 2, 3, [4, 5]] 默認(rèn)只會“拉平”一層 [1, 2, , [3, [4, 5]]].flat(2); // [1, 2, 3, 4, 5] 參數(shù)為2,表示要“拉平”兩層的嵌套數(shù)組,會跳過空位 [1, [2, [3]]].flat(Infinity); // [1, 2, 3] Infinity關(guān)鍵字作為參數(shù),不管有多少層嵌套,都要轉(zhuǎn)成一維數(shù)組
flatMap()方法對原數(shù)組的每個成員執(zhí)行一個函數(shù)(相當(dāng)于執(zhí)行Array.prototype.map()),然后回返回值組成的數(shù)組執(zhí)行flat()方法(默認(rèn)只能展開一層)。該方法返回一個新數(shù)組,不改變原數(shù)組。
[1, 2, 3, 4].flatMap(x => [[x * 2]]) // [[2], [4], [6], [8]] 相當(dāng)于[[[2]], [[4]], [[6]], [[8]]].flat()
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/105574.html
摘要:在我們經(jīng)常用到固定頭部和底部,自適應(yīng)中間部分,或者固定左側(cè),自適應(yīng)右側(cè)等。在網(wǎng)上看了很多方法,一般都是通過絕對定位完成,具體可以網(wǎng)上去搜,這樣可以完成上中下的布局,但是這次基礎(chǔ)上再做左右布局浮動會出現(xiàn)問題,具體什么問題我沒有深究。 在css我們經(jīng)常用到固定頭部和底部,自適應(yīng)中間部分,或者固定左側(cè),自適應(yīng)右側(cè)等。在網(wǎng)上看了很多方法,一般都是通過絕對定位完成,position: absol...
摘要:基本布局上中左右下布局頭部左側(cè)超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出 基本布局1: 上中(左右)下布局 html,body{ margin:0; height:100%; ove...
摘要:基本布局上中左右下布局頭部左側(cè)超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出現(xiàn)滾動條超過高度出 基本布局1: 上中(左右)下布局 html,body{ margin:0; height:100%; ove...
摘要:代理模式的擴(kuò)展普通代理這種代理就是客戶端只能訪問代理角色,而不能訪問真實角色。與設(shè)計模式之蟬代理模式上片基本差不多。 代理模式的擴(kuò)展 1 普通代理 :這種代理就是客戶端只能訪問代理角色,而不能訪問真實角色。與設(shè)計模式之蟬——代理模式上 片基本差不多。(1)Subject抽象主題角色: showImg(https://segmentfault.com/img/bVbh8S5?w=1954...
摘要:本書屬于基礎(chǔ)類書籍,會有比較多的基礎(chǔ)知識,所以這里僅記錄平常不怎么容易注意到的知識點,不會全記,供大家和自己翻閱不錯,下冊的知識點就這么少,非常不推介看下冊上中下三本的讀書筆記你不知道的上讀書筆記你不知道的中讀書筆記你不知道的下讀書筆記第三 本書屬于基礎(chǔ)類書籍,會有比較多的基礎(chǔ)知識,所以這里僅記錄平常不怎么容易注意到的知識點,不會全記,供大家和自己翻閱; 不錯,下冊的知識點就這么少,非...
閱讀 3925·2021-10-12 10:12
閱讀 2886·2021-09-10 11:18
閱讀 3673·2019-08-30 15:54
閱讀 2808·2019-08-30 15:53
閱讀 638·2019-08-30 13:54
閱讀 965·2019-08-30 13:21
閱讀 2260·2019-08-30 12:57
閱讀 1687·2019-08-30 11:10