ES6學(xué)習(xí)筆記——函數(shù)的拓展

函數(shù)的拓展

函數(shù)默認(rèn)值

到了ES6轻庆,函數(shù)終于有默認(rèn)值了市栗,在ES5中其實(shí)是可以用一些變通的方法來(lái)完成參數(shù)默認(rèn)的鲫骗,但是有一些缺點(diǎn),比如說(shuō)如果參數(shù)賦值了杠人,但是對(duì)應(yīng)的布爾值為false勋乾,則該賦值不起作用。ES6就解決了這個(gè)問(wèn)題嗡善。

// ES5
function log(x, y) {
  y = y || 'World';
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World 出現(xiàn)問(wèn)題

// ES6
function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello 沒(méi)毛病

參數(shù)變量是默認(rèn)聲明的辑莫,所以不能用let或者const再次聲明

function foo(x = 5) {
  let x = 1; // error
  const x = 2; // error
}

使用參數(shù)默認(rèn)值時(shí),函數(shù)不能有同名參數(shù)

// 不報(bào)錯(cuò)
function foo(x, x, y) {
  // ...
}

// 報(bào)錯(cuò)
function foo(x, x, y = 1) {
  // ...
}
// SyntaxError: Duplicate parameter name not allowed in this context

參數(shù)默認(rèn)值不是傳值的罩引,而是每次都重新計(jì)算默認(rèn)值表達(dá)式的值各吨。也就是說(shuō),參數(shù)默認(rèn)值是惰性求值的

let x = 99;
function foo(p = x + 1) {
  console.log(p);
}

foo() // 100

x = 100;
foo() // 101

每次調(diào)用都重新計(jì)算

與解構(gòu)賦值默認(rèn)值結(jié)合使用

參數(shù)默認(rèn)值可以和解構(gòu)賦值的默認(rèn)值袁铐,結(jié)合起來(lái)使用揭蜒。
更騷氣的是如果參數(shù)時(shí)一個(gè)對(duì)象,對(duì)象里面做了默認(rèn)值剔桨,比如{x, y=5}屉更,這個(gè)時(shí)候如果啥也不傳就會(huì)報(bào)錯(cuò),這個(gè)時(shí)候可以通過(guò)提供函數(shù)參數(shù)的默認(rèn)值洒缀,避免報(bào)錯(cuò)瑰谜。

function foo({x, y = 5} = {}) {
  console.log(x, y);
}

foo() // undefined 5

function fetch(url, { body = '', method = 'GET', headers = {} }) {
  console.log(method);
}

fetch('http://example.com', {})
// "GET"

fetch('http://example.com')

function fetch(url, { method = 'GET' } = {}) {
  console.log(method);
}

fetch('http://example.com')
// "GET"

出現(xiàn)了雙重默認(rèn)值。

參數(shù)默認(rèn)值的位置

通常情況下树绩,定義了默認(rèn)值的參數(shù)萨脑,應(yīng)該是函數(shù)的尾參數(shù)。因?yàn)檫@樣比較容易看出來(lái)饺饭,到底省略了哪些參數(shù)渤早。如果非尾部的參數(shù)設(shè)置默認(rèn)值,實(shí)際上這個(gè)參數(shù)是沒(méi)法省略的瘫俊。

// 例一
function f(x = 1, y) {
  return [x, y];
}

f() // [1, undefined]
f(2) // [2, undefined])
f(, 1) // 報(bào)錯(cuò)
f(undefined, 1) // [1, 1]

// 例二
function f(x, y = 5, z) {
  return [x, y, z];
}

f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 報(bào)錯(cuò)
f(1, undefined, 2) // [1, 5, 2]

上述情況都不能省略參數(shù)鹊杖,只能設(shè)置undefined來(lái)觸發(fā)等于默認(rèn)值提鸟。但是null沒(méi)有這個(gè)效果。

函數(shù)的長(zhǎng)度(length)

函數(shù)的屬性length返回函數(shù)沒(méi)有指定默認(rèn)值的參數(shù)的個(gè)數(shù)仅淑,如果指定了默認(rèn)參數(shù),那么將不計(jì)入length胸哥,length永遠(yuǎn)返回沒(méi)有默認(rèn)參數(shù)的傳入?yún)?shù)個(gè)數(shù)涯竟。

(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2

有趣的是這個(gè)length的計(jì)數(shù)是根據(jù)默認(rèn)參數(shù)的位置來(lái)計(jì)算的,果設(shè)置了默認(rèn)值的參數(shù)不是尾參數(shù)空厌,那么length屬性也不再計(jì)入后面的參數(shù)了庐船。

(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1

作用域

一旦設(shè)置了參數(shù)的默認(rèn)值,函數(shù)進(jìn)行聲明初始化時(shí)嘲更,參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域筐钟。等到初始化結(jié)束,這個(gè)作用域也就消失了赋朦。

var x = 1;

function f(x, y = x) {
  console.log(y);
}

f(2) // 2

let x = 1;

function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // 1

上面兩種情況篓冲,第一種就是指向第一個(gè)x,外面全局的x不會(huì)影響y的賦值宠哄。但是第二種情況因?yàn)閤本身沒(méi)有定義壹将,所以會(huì)指向外部全局的x,但是在內(nèi)部x的操作毛嫉,并不會(huì)影響到y(tǒng)的值诽俯。

應(yīng)用

利用參數(shù)默認(rèn)值,可以指定某一個(gè)參數(shù)不得省略承粤,如果省略就拋出錯(cuò)誤暴区。

function throwIfMissing() {
  throw new Error('Missing parameter');
}

function foo(mustBeProvided = throwIfMissing()) {
  return mustBeProvided;
}

foo()
// Error: Missing parameter

rest參數(shù)

ES5中函數(shù)傳參可以用arguments,在ES6加入了rest參數(shù)來(lái)使得傳參更加地優(yōu)雅辛臊,用法為...變量名仙粱。

function add(...values) {
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2, 5, 3) // 10

注意,rest參數(shù)必須是最后一個(gè)參數(shù)浪讳,否則會(huì)報(bào)錯(cuò)

嚴(yán)格模式

ES5開(kāi)始函數(shù)內(nèi)部可以設(shè)定為嚴(yán)格模式缰盏,但是ES6引入默認(rèn)值、解構(gòu)賦值淹遵、擴(kuò)展運(yùn)算符之后口猜,函數(shù)內(nèi)部就不可以使用嚴(yán)格模式了,否則就會(huì)報(bào)錯(cuò)透揣。

因?yàn)楹瘮?shù)內(nèi)部的嚴(yán)格模式济炎,同樣適用于函數(shù)體和函數(shù)參數(shù),但是函數(shù)執(zhí)行的時(shí)候辐真,先執(zhí)行函數(shù)參數(shù)须尚,然后執(zhí)行函數(shù)體崖堤,這就不合理了,只有從函數(shù)體之中耐床,才能知道參數(shù)是否應(yīng)該以嚴(yán)格模式執(zhí)行密幔,但是參數(shù)應(yīng)該先初始化。

當(dāng)然了撩轰,你可以吧“use strict”放在外面或者用一個(gè)立即執(zhí)行的函數(shù)包住函數(shù)胯甩。

'use strict';

function doSomething(a, b = a) {
  // code
}

const doSomething = (function () {
  'use strict';
  return function(value = 42) {
    return value;
  };
}());

name屬性

函數(shù)的name屬性,直接返回函數(shù)的名字堪嫂,有很多種情況偎箫,比如匿名函數(shù)還有bind的函數(shù)等,詳見(jiàn)代碼皆串。

var f = function () {};

// ES5
f.name // ""

// ES6
f.name // "f"

const bar = function baz() {};

// ES5
bar.name // "baz"

// ES6
bar.name // "baz"

(new Function).name // "anonymous"

function foo() {};
foo.bind({}).name // "bound foo"

(function(){}).bind({}).name // "bound "

箭頭函數(shù)

ES6的箭頭表達(dá)式是非常有用的一個(gè)東西淹办。哇,真的方便恶复。

如果箭頭函數(shù)不需要參數(shù)或需要多個(gè)參數(shù)怜森,就使用一個(gè)圓括號(hào)代表參數(shù)部分。

var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

如果箭頭函數(shù)的代碼塊部分多于一條語(yǔ)句寂玲,就要使用大括號(hào)將它們括起來(lái)塔插,并且使用return語(yǔ)句返回。

var sum = (num1, num2) => { return num1 + num2; }
由于大括號(hào)被解釋為代碼塊拓哟,所以如果箭頭函數(shù)直接返回一個(gè)對(duì)象想许,必須在對(duì)象外面加上括號(hào),否則會(huì)報(bào)錯(cuò)断序。

// 報(bào)錯(cuò)
let getTempItem = id => { id: id, name: "Temp" };

// 不報(bào)錯(cuò)
let getTempItem = id => ({ id: id, name: "Temp" });

如果箭頭函數(shù)只有一行語(yǔ)句流纹,且不需要返回值,可以采用下面的寫法违诗,就不用寫大括號(hào)了漱凝。

let fn = () => void doesNotReturn();

箭頭函數(shù)可以與變量解構(gòu)結(jié)合使用。

const full = ({ first, last }) => first + ' ' + last;

// 等同于
function full(person) {
  return person.first + ' ' + person.last;
}

箭頭函數(shù)使得表達(dá)更加簡(jiǎn)潔诸迟。
箭頭函數(shù)的一個(gè)用處是簡(jiǎn)化回調(diào)函數(shù)茸炒。

// 正常函數(shù)寫法
[1,2,3].map(function (x) {
  return x * x;
});

// 箭頭函數(shù)寫法
[1,2,3].map(x => x * x);
另一個(gè)例子是

// 正常函數(shù)寫法
var result = values.sort(function (a, b) {
  return a - b;
});

// 箭頭函數(shù)寫法
var result = values.sort((a, b) => a - b);

下面是 rest 參數(shù)與箭頭函數(shù)結(jié)合的例子。

const numbers = (...nums) => nums;

numbers(1, 2, 3, 4, 5)
// [1,2,3,4,5]

const headAndTail = (head, ...tail) => [head, tail];

headAndTail(1, 2, 3, 4, 5)
// [1,[2,3,4,5]]

注意點(diǎn)

  • 函數(shù)體內(nèi)的this對(duì)象阵苇,就是定義時(shí)所在的對(duì)象壁公,而不是使用時(shí)所在的對(duì)象
  • 不可以當(dāng)作構(gòu)造函數(shù),也就是說(shuō)绅项,不可以使用new命令紊册,否則會(huì)拋出一個(gè)錯(cuò)誤
  • 不可以使用arguments對(duì)象,該對(duì)象在函數(shù)體內(nèi)不存在快耿。如果要用囊陡,可以用 rest 參數(shù)代替
  • 不可以使用yield命令芳绩,因此箭頭函數(shù)不能用作 Generator 函數(shù)

第一點(diǎn)尤其值得注意。this對(duì)象的指向是可變的撞反,但是在箭頭函數(shù)中妥色,它是固定的

綁定this

箭頭函數(shù)可以綁定this對(duì)象,這就可以減少bind顯式的調(diào)用遏片。

函數(shù)綁定運(yùn)算符是并排的兩個(gè)冒號(hào)(::)垛膝,雙冒號(hào)左邊是一個(gè)對(duì)象,右邊是一個(gè)函數(shù)丁稀。該運(yùn)算符會(huì)自動(dòng)將左邊的對(duì)象,作為上下文環(huán)境(即this對(duì)象)倚聚,綁定到右邊的函數(shù)上面线衫。

如果雙冒號(hào)左邊為空,右邊是一個(gè)對(duì)象的方法惑折,則等于將該方法綁定在該對(duì)象上面授账。

由于雙冒號(hào)運(yùn)算符返回的還是原對(duì)象,因此可以采用鏈?zhǔn)綄懛ā?/p>

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return obj::hasOwnProperty(key);
}

var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;

let log = ::console.log;
// 等同于
var log = console.log.bind(console);

// 例一
import { map, takeWhile, forEach } from "iterlib";

getPlayers()
::map(x => x.character())
::takeWhile(x => x.strength > 100)
::forEach(x => console.log(x));

// 例二
let { find, html } = jake;

document.querySelectorAll("div.myClass")
::find("p")
::html("hahaha");

尾逗號(hào)

ES6支持參數(shù)的最后一個(gè)后面可以接一個(gè)逗號(hào)

function clownsEverywhere(
  param1,
  param2,
) { /* ... */ }

clownsEverywhere(
  'foo',
  'bar
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惨驶,一起剝皮案震驚了整個(gè)濱河市白热,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌粗卜,老刑警劉巖屋确,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異续扔,居然都是意外死亡攻臀,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門纱昧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)刨啸,“玉大人,你說(shuō)我怎么就攤上這事识脆∩枇” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵灼捂,是天一觀的道長(zhǎng)离例。 經(jīng)常有香客問(wèn)我,道長(zhǎng)纵东,這世上最難降的妖魔是什么粘招? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮偎球,結(jié)果婚禮上洒扎,老公的妹妹穿的比我還像新娘辑甜。我一直安慰自己,他們只是感情好袍冷,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布磷醋。 她就那樣靜靜地躺著,像睡著了一般胡诗。 火紅的嫁衣襯著肌膚如雪邓线。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天煌恢,我揣著相機(jī)與錄音骇陈,去河邊找鬼。 笑死瑰抵,一個(gè)胖子當(dāng)著我的面吹牛你雌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播二汛,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼婿崭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了肴颊?” 一聲冷哼從身側(cè)響起氓栈,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎婿着,沒(méi)想到半個(gè)月后授瘦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡竟宋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年奥务,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袜硫。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡氯葬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婉陷,到底是詐尸還是另有隱情帚称,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布秽澳,位于F島的核電站闯睹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏担神。R本人自食惡果不足惜楼吃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孩锡,春花似錦酷宵、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至荣挨,卻和暖如春男韧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背默垄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工此虑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人口锭。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓寡壮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親讹弯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 函數(shù)參數(shù)的默認(rèn)值 基本用法 在ES6之前这溅,不能直接為函數(shù)的參數(shù)指定默認(rèn)值组民,只能采用變通的方法。 上面代碼檢查函數(shù)l...
    呼呼哥閱讀 3,357評(píng)論 0 1
  • 三悲靴,字符串?dāng)U展 3.1 Unicode表示法 ES6 做出了改進(jìn)臭胜,只要將碼點(diǎn)放入大括號(hào),就能正確解讀該字符癞尚。有了這...
    eastbaby閱讀 1,514評(píng)論 0 8
  • 1.函數(shù)參數(shù)的默認(rèn)值 (1).基本用法 在ES6之前耸三,不能直接為函數(shù)的參數(shù)指定默認(rèn)值,只能采用變通的方法浇揩。
    趙然228閱讀 683評(píng)論 0 0
  • 第一章 塊級(jí)作用域綁定 let 和 const 都是不存在提升胳徽,聲明的都是塊級(jí)標(biāo)識(shí)符都禁止重聲明 每個(gè)const聲...
    NowhereToRun閱讀 1,573評(píng)論 0 2
  • 超喜歡霧紗的我今天忍不住就來(lái)了一幅积锅,不過(guò)這次的線稿有些瑕疵。線稿還有待于提高养盗!不過(guò)令人高興的是我目前對(duì)于人物的上色...
    我是胖少閱讀 319評(píng)論 0 0