函数的扩展

173 阅读3分钟

函数参数的默认值

基本用法

  • 函数变量是默认声明的,所以不能用 let 或 const 再次声明
  • 参数默认值不是传值的(计算表达式),每次都会重新计算默认值表达式的值
  • 默认值的参数不是尾参数时,不能省略该参数而不省略后边的参数,除非显示输入 undefined
  • 参数传入 undefined 时才能触发该参数的默认值, null 不可以
function foo(x = 3) {
    // 以下两个语句都会报错
    let x = 1;
    const x = 2;
}

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

bar(); // 100

x = 100;
bar(); // 101

function too(x, y = 5, z) {
    return [x, y, z];
}
too(); // [undefined, 5, undefined]
too(1); // [1, 5, undefined]
too(1, , 2); // 报错
too(1, undefined, 2); // [1, 5, 2]

function far(x = 5, y = 6) {
    return [x, y];
}
far(undefined, null); // [5, undefined]

函数的 length 属性

指定默认值以后,函数的 length 属性将返回没有指定默认值的参数个数。若设置默认值的参数不是尾参数,那么后面的参数也不计入 length 属性。同理, rest 参数不会计入 length 属性。

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

严格模式

ES5开始,函数内部可以设定为严格模式。ES6规定只要函数参数使用了默认值、解构赋值或扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错

name 属性

函数的 name 属性返回该函数的函数名。

如果将一个具名函数赋值给一个变量, name 属性返回具名函数原来的名字。

Function 构造函数返回的函数实例, name 属性的值为 anonymous。

bind 返回的函数, name 属性值会加上 bound 前缀。

var f = function () {};
f.name // ES5——"",ES6——"f"

const bar = function baz() {};
bar.name // "baz"

(New Function).name // anonymous

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

箭头函数

箭头函数使用时注意事项:

  • 函数体内的 this 对象就是定义时所在的对象,而不是使用时所在的对象。箭头函数没有自己的 this 对象,导致内部的 this 就是外层代码的 this
  • 不可以当做构造函数
  • 不可以使用 arguments 对象,该对象在函数体内不存在
  • 不可以使用 yield 命令

函数绑定运算符

"::"——函数绑定运算符,双冒号左边是一个对象,右边是一个函数。表示将左边的对象作为上下文环境(即 this 对象)绑定到右边的函数上。如果双冒号左边为空,右边是一个对象的方法,表示将该方法绑定在该对象上。

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

obj::obj.foo;
// 等同于
::obj.foo;

尾调用优化

尾调用是指某个函数的最后一步是调用另一个函数。尾调用优化就是只保留内层函数的调用帧。尾调用优化只在严格模式下开启。

// 尾调用
function f(x) {
    return g(x);
}
function g(x) {
    if (x > 0) {
        return m(x);
    }
    return n(x);
}

// 以下三种情况不是尾调用
// 情况一,调用函数 g 之后还用赋值操作
function f(x) {
    let y = g(x);
    return y;
}
// 情况二,调用后还有操作
function f(x) {
    return g(x) + 1;
}
// 情况三,等同于
// function f(x) {
//	g(x);
//	return undefined;
// }
function f(x) {
    g(x);
}