ES6_08- 函数的扩展

本文详细介绍了ES6中的函数参数默认值、rest参数、name属性以及箭头函数的使用。通过实例展示了如何设置函数参数默认值,解释了length属性的变化,并探讨了函数参数默认值产生的作用域问题。此外,还讲解了rest参数如何替代arguments对象,以及箭头函数的简洁语法、this值的继承特性及其适用场景。最后,提到了箭头函数在定义对象方法时的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用



1. 函数参数默认值

1.1. 基本用法

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

1.2. 与解构赋值默认值结合使用

        // 写法一
function m1({x = 0, y = 0} = {}) {
  return [x, y];
}

// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}

// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]

// x 和 y 都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]

// x 有值,y 无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]

// x 和 y 都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]

m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]

1.3. 函数length属性

  • 指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
  • 设置了默认值的参数,其之后的参数是不计入length的。
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1

1.4. *************函数参数默认值引起的第三作用域问题

  • 一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的
  • 参考这篇文章
    关于 ES6 参数默认值形成的第三作用域问题
  • 上面这篇文章的小节:
    1 .函数形参指定了默认值时,将形成一个第三作用域,即参数作用域,此作用域将作为函数作用域的父级。
    2 .函数内let声明的局部变量名与形参名一致时,在解析阶段就会报错。
    3 .函数内诸如var x(未赋值)声明的局部变量名与形参名一致时,可忽略当前代码行。
var x = 20;
function fun(x = 1) {
   let x = 10; // SyntaxError: Identifier 'x' has already been declared
   console.log(x);
}
fun();
var x = 1;

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

f(2) // 2
// 调用函数f时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x指向第一个参数x,而不是全局变量x,所以输出是2。
let x = 1;

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

f() // 1
// 函数f调用时,参数y = x形成一个单独的作用域。这个作用域里面,变量x本身没有定义,所以指向外层的全局变量x。函数调用时,函数体内部的局部变量x影响不到默认值变量x。
function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // ReferenceError: x is not defined
var x = 1;

function foo(x = x) {
  // ...
}

foo() // ReferenceError: Cannot access 'x' before initialization
// 参数x = x形成一个单独作用域。实际执行的是let x = x,由于暂时性死区的原因,这行代码会报错。

2. rest参数

  • ES6 引入 rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
  • arguments对象不是数组,而是一个类似数组的对象。为了使用数组的方法,必须使用Array.from先将其转为数组。
  • rest 参数就不存在这个问题,它就是一个真正的数组,数组特有的方法都可以使用。
// arguments变量的写法
function sortNumbers() {
  return Array.from(arguments).sort();
}

// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();
  • rest 只能是最后一个参数,否则会报错。
// 报错
function f(a, ...b, c) {
  // ...
}
  • 函数的length属性,不包括 rest 参数。
(function(a) {}).length  // 1
(function(...a) {}).length  // 0
(function(a, ...b) {}).length  // 1

3. name属性

  • 函数的name属性,返回该函数的函数名。
function foo() {}
foo.name // "foo"
  • 将一个匿名函数赋值给一个变量,ES5 的name属性,会返回空字符串,而 ES6 的name属性会返回实际的函数名
var f = function () {};

// ES5
f.name // ""

// ES6
f.name // "f"
  • 将一个具名函数赋值给一个变量,则 ES5 和 ES6 的name属性都返回这个具名函数原本的名字
const bar = function baz() {};

// ES5
bar.name // "baz"

// ES6
bar.name // "baz"

4. 箭头函数

4.1. 写法

  • 基本写法
        function() { }
        等于
        ()=> { }
  • 无参数
        let fn = () => 'hello world';
  • 一个参数
        let add = val => { return val };
        let add = val => (val);
        let add = val => val;

        let add = val => { return val + 5 };
        let add = val => (val + 5);
        let add = val => val + 5;
  • 两个及多个参数
        let happiness = (you, i) => { return you + ' love ' + i + ' ,' + i + ' love ' + you + ' ♡' }
        let happiness = (you, i) => (you + ' love ' + i + ' ,' + i + ' love ' + you + ' ♡')
        let happiness = (you, i) => you + ' love ' + i + ' ,' + i + ' love ' + you + ' ♡'

        console.log(happiness('FU', 'CW'));
        // FU love CW ,CW love FU ♡

4.2. 优点

  1. 语法简明
        // 与rest函数结合,高效变数组
        const numbers = (...nums) => nums;
        console.log(numbers(1, 2, 3, 4, 5)); //[1, 2, 3, 4, 5]
  1. 简化回调函数,隐式返回
        const pingfang = [1, 2, 3].map(x => x * x);
        console.log(pingfang); // [1, 4, 9]
  1. this值继承父作用域

4.3. 使用注意点

  1. 箭头函数没有自己的this对象。
  2. 不能当作构造函数,不可以对箭头函数使用new命令。
  3. 不可以使用arguments对象。
  4. 不能使用apply() call() bind() 去改变this的指向。

4.4. 不适宜场合

  1. 定义对象的方法,且该方法内部包括this。
    由于这个原因,对象的属性建议使用传统的写法定义,不要用箭头函数定义。
const cat = {
  lives: 9,
  jumps: () => {
    this.lives--;
  }
}

  • 上面代码,this指向全局对象,不会得到预期结果。这是因为对象不构成单独的作用域,导致jumps箭头函数定义时的作用域就是全局作用域。
  1. 需要动态this的时候。
var button = document.getElementById('press');
button.addEventListener('click', () => {
  this.classList.toggle('on');
});
  • 上面代码运行时,点击按钮会报错,因为button的监听函数是一个箭头函数,导致里面的this就是全局对象。如果改成普通函数,this就会动态指向被点击的按钮对象。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值