OLD函數(shù)默認(rèn)參數(shù)
// 缺點(diǎn):布爾值為false的變量都會被賦為默認(rèn)值
function fn(x) {
x = x || 'hello'
}
// 比較麻煩
function fn (x) {
if (typefo x === 'undefined') {
x = 'hello'
}
}
基本用法
在 ES2017 中,允許定義和調(diào)用函數(shù)時有缆,最后一個參數(shù)有
,
惰性求值
let x = 99;
function foo(p = x + 1) {
console.log(p);
}
foo() // 100
x = 100;
foo() // 101
報錯情景
- 當(dāng)函數(shù)參數(shù)
x
有默認(rèn)值折剃,再在函數(shù)中聲明就會報錯 - 當(dāng)函數(shù)參數(shù)都沒有默認(rèn)值华临,允許參數(shù)同名是鬼。只要函數(shù)參數(shù)有一個就沒有默認(rèn)值,就不允許函數(shù)參數(shù)同名纲刀。
- 當(dāng)函數(shù)參數(shù)有對象解構(gòu)的情況项炼,函數(shù)對象中的屬性不能和其它參數(shù)同名
// 情景3 ---- 報錯
function fn (x,{x = 1,n = 2}={}) {
console.log(x,n)
}
fn('yy');
函數(shù)參數(shù)對象
function fn({x,y=1}) {
console.log(x,y)
}
fn({}) // undefined,1
fn() // 報錯
- 報錯原因担平,當(dāng)沒有參數(shù)時,其實(shí)默認(rèn)參數(shù)為
undefined
锭部。對象和undefined
發(fā)生解構(gòu)報錯暂论。 - 正確原因,傳入對象拌禾,發(fā)生解構(gòu)取胎,x沒有默認(rèn)解構(gòu)值,則為undefined,y有默認(rèn)解構(gòu)值湃窍,則為1
function fn({x,y=1} = {}) {
console.log(x,y)
}
fn({}) // undefined,1
fn() // undefined,1
-
fn()
執(zhí)行過程如下
- 調(diào)用
fn
闻蛀,沒有參數(shù),使用函數(shù)默認(rèn)參數(shù){}
- 發(fā)生對象解構(gòu)您市,x沒有解構(gòu)默認(rèn)值觉痛,y有默認(rèn)解構(gòu)值
// 分析以下案例
// 寫法一
function m1({x = 0, y = 0} = {}) {
return [x, y];
}
// 寫法二
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
默認(rèn)值位置
- 應(yīng)該時函數(shù)的尾參數(shù)
- 有默認(rèn)值,會影響
fn.length
- 一般是
fn.length - 默認(rèn)參數(shù)個數(shù)
- 當(dāng)默認(rèn)參數(shù)不是尾參數(shù)茵休,
fn.length
是第一個默認(rèn)參數(shù)之前的參數(shù)的個數(shù) - 當(dāng)參數(shù)是
...rest
,fn.length
是0
作用域
當(dāng)函數(shù)有默認(rèn)值時薪棒,參數(shù)會形成一個獨(dú)立的作用域
簡單案例
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
function ff (y = x) {
console.log(y);
}
- 函數(shù)
f
的參數(shù)形成一個默認(rèn)作用域。函數(shù)初始化過程
- 參數(shù)
x
被賦值為2 - 參數(shù)
y
被賦值為x
榕莺,在當(dāng)前作用域中找x
俐芯,找到x = 2
,因此y = 2
- 函數(shù)初始化過程
- 沒有參數(shù)
x
- 參數(shù)
y
被賦值為x
钉鸯,在當(dāng)前作用域中沒有x
吧史,找到全局變量x
,因此y = 1
參數(shù)為函數(shù)的案例
var x = 1;
function foo(x, y = function() { x = 2; }) {
var x = 3;
y();
console.log(x);
}
foo() // 3
x // 1
- 函數(shù)初始化
- 參數(shù)
x
沒有默認(rèn)值亏拉,因此扣蜻,在函數(shù)foo
中再聲明x
不會報錯 - 在函數(shù)
foo
的參數(shù)作用域中,x
先為undefined
及塘,在調(diào)用y
時,x
是參數(shù)而不是全局變量x
锐极,此時參數(shù)x
改為2 - 但是由于笙僚,在函數(shù)再次聲明了
x
,這個x
完全不是參數(shù)灵再,因此函數(shù)foo
打印x
為3
- 當(dāng)去掉
var x = 3
肋层,函數(shù)foo
的參數(shù),其實(shí)相當(dāng)于聲明并賦值參數(shù)x
翎迁,沒有函數(shù)內(nèi)部變量x
栋猖,參數(shù)x
就會被打印。
rest參數(shù)
- 形式汪榔,
function fn(...rest)
- rest參數(shù)是數(shù)組蒲拉,之后不允許有參數(shù)
嚴(yán)格模式
- 函數(shù)中可以使用
use strict
設(shè)置嚴(yán)格模式 - 當(dāng)函數(shù)參數(shù)有默認(rèn)值,解構(gòu)賦值,擴(kuò)展運(yùn)算符時雌团,不允許使用嚴(yán)格模式
- 有兩種方法可以規(guī)避以上規(guī)則
- 全局嚴(yán)格模式
- 在立即調(diào)用的函數(shù)中使用嚴(yán)格模式
name屬性
-
name
屬性使用方式fnName.name
function fn() {} // fn.name--->fn
var fn = function () {} // fn.name--->fn
var fn = function fun() {} // fn.name----->fun
fn.bind({},1) // fn.name---->bound fn
(new Function).name // ----> anonymous
(function () {}).name //---->''
箭頭函數(shù)
箭頭函數(shù)結(jié)構(gòu)
functionName = (arg1,arg2) => {arg1 + arg2};
- 其中函數(shù)名省略燃领,則為匿名函數(shù)
- 根據(jù)參數(shù)情況也可以省略
- 當(dāng)沒有參數(shù)或者兩個及兩個以上參數(shù)時,
(
小括號不可省略 - 當(dāng)有一個參數(shù)時锦援,小括號可以省略
- 當(dāng)函數(shù)體只有一條語句猛蔽,可以省略
{
大括號,并默認(rèn)有return
返回灵寺。當(dāng)不需要返回值時
- 即使一條語句也加上
{
曼库,這樣就沒有返回值 - 使用
void (一條語句)
,這樣也沒有返回值
var fn = (x,y) => x + y;
// 等價于
function fn (x,y) {
return x + y;
}
箭頭函數(shù)
-
this
固定略板,指向定義時的this - 箭頭函數(shù)不能做構(gòu)造函數(shù)
- 不能使用
arguments
- 不能使用
yield
毁枯,也就是箭頭函數(shù)不能做Generator
注意點(diǎn)
- 箭頭函數(shù)中沒有自己的
this
,只是引用外層的this
- 箭頭函數(shù)無法使用
call()
,apply()
,bind()
改變this
執(zhí)行
分析過程(一)
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
var id = 21;
foo.call({ id: 42 });
// result: 42
- 當(dāng)執(zhí)行
foo.call({id: 42})
內(nèi)部的this
指向{id: 42}
- 此時蚯根,箭頭函數(shù)沒有自己的
this
后众。外部的this
就是{id:42}
- 即使100毫秒后,在
setTimeout
中颅拦,this
也不改變?yōu)?code>window
分析過程(二)
function foo() {
setTimeout(function() {
console.log('id:', this.id);
}, 100);
}
var id = 21;
foo.call({ id: 42 });
// result: 21
- 普通函數(shù)蒂誉,
this
指向運(yùn)行時的上下文環(huán)境 -
setTimeout
偽代碼function setTimeout() {//delay... callback();}
,可以看到callback
函數(shù),也就是普通函數(shù)的沒有綁定到其它對象上
尾調(diào)用
- 最后一步調(diào)用其它函數(shù)距帅,稱為尾調(diào)用
- 尾調(diào)用函數(shù)定義時右锨,不使用外層函數(shù)的變量
- 尾調(diào)用,有利于節(jié)約內(nèi)存
// 這種情況沒有使用外層函數(shù)的變量
function f() {
let m = 1;
let n = 2;
return g(m + n); // 最后一步用
}
f();
// 這種情況使用了外層函數(shù)的變量
function f() {
let m = 1;
function g(n) {
return m + n;
}
return g(2); // 最后一步用
}
f();