函数扩展
函数参数的默认值
设置函数默认值
function Point(x = 0, y = 0) {
this.x = x;
this.y = y;
}
const p = new Point();
p // { x: 0, y: 0 }
表达式 赋默认值
let x = 99;
function foo(p = x + 1) {
console.log(p);
}
foo() // 100
x = 100;
foo() // 101
与解构赋值默认值结合使用
参数默认值可以与解构赋值的默认值,结合起来使用。
function foo({x, y = 5}) {
console.log(x, y);
}
foo({}) // undefined 5
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined
默认值参数必须是函数的尾参数
默认参数必须是尾参数,要不然不能省略,必须用undefined补充
// 例一
function f(x = 1, y) {
return [x, y];
}
f() // [1, undefined]
f(2) // [2, undefined])
f(, 1) // 报错
f(undefined, 1) // [1, 1]
函数的length属性
函数的length属性返回的是没有默认值的参数个数
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
作用域
设置了参数默认值 函数在声明初始化时 参数会形成一个单独的作用域
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
应用
可以指定某一参数不能省略
function throwIfMissing() {
throw new Error('Missing parameter');
}
function foo(mustBeProvided = throwIfMissing()) {
return mustBeProvided;
}
foo()
rest参数
用于获取对于参数
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
严格模式
//不怎么用 不做赘述
name属性
函数的name属性
function foo() {}
foo.name // "foo"
const bar = function baz() {};
// ES5
bar.name // "baz"
// ES6
bar.name // "baz"
箭头函数
箭头函数的this对象是定义时的对象,不是调用时的对象
var f = v => v; //一个参数 一条语句
//等同于
var f = function(v) {
return v;
};
var f = () => 5; // 无参数
let getTempItem = id => ({ id: id, name: "Temp" }); 直接返回一个对象
不写大括号 可以就是默认返回语句运算结果 不需要写return
注意点:
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。 箭头函数内部的变量arguments,其实是函数foo的arguments
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
双冒号运算符
可以用::双冒号运算符取代call,apply,bind绑定对象
foo::bar;
// 等同于
bar.bind(foo);
foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);
左边为空时 右边是一个对象的方法 等于将该方法绑定在该对象的上面
var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;
let log = ::console.log;
// 等同于
var log = console.log.bind(console);
尾调用优化
在最后一步调用另一个函数,并返回
function f(x){
return g(x);
}
只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是“尾调用优化”的意义。
尾递归
函数自身调用自身,在末尾调用并返回
function factorial(n) {
if (n === 1) return 1;
return n * factorial(n - 1);
}
factorial(5) // 120
//不是尾递归 会栈内存溢出
function factorial(n, total) {
if (n === 1) return total;
return factorial(n - 1, n * total);
}
factorial(5, 1) // 120
//尾递归