整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

深入理解JavaScript中的箭头函数

我们深入研究一下箭头函数。

箭头函数不仅仅是编写简洁代码的“捷径”。它还具有非常特殊且有用的特性。

JavaScript 充满了我们需要编写在其他地方执行的小函数的情况。

例如:

  • arr.forEach(func) —— forEach 对每个数组元素都执行 func
  • setTimeout(func) —— func 由内建调度器执行。
  • ……还有更多。

JavaScript 的精髓在于创建一个函数并将其传递到某个地方。

在这样的函数中,我们通常不想离开当前上下文。这就是箭头函数的主战场啦。

一、箭头函数没有 “this”

正如我们在 对象方法,"this" 一章中所学到的,箭头函数没有 this。如果访问 this,则会从外部获取。

例如,我们可以使用它在对象方法内部进行迭代:

let group = {
  title: "Our Group",
  students: ["John", "Pete", "Alice"],

  showList() {
    this.students.forEach(
      student => alert(this.title + ': ' + student)
    );
  }
};

group.showList();

这里 forEach 中使用了箭头函数,所以其中的 this.title 其实和外部方法 showList 的完全一样。那就是:group.title

如果我们使用正常的函数,则会出现错误:

let group = {
  title: "Our Group",
  students: ["John", "Pete", "Alice"],

  showList() {
    this.students.forEach(function(student) {
      // Error: Cannot read property 'title' of undefined
      alert(this.title + ': ' + student)
    });
  }
};

group.showList();

报错是因为 forEach 运行它里面的这个函数,但是这个函数的 this 为默认值 this=undefined,因此就出现了尝试访问 undefined.title 的情况。

但箭头函数就没事,因为它们没有 this

不能对箭头函数进行 new 操作

不具有 this 自然也就意味着另一个限制:箭头函数不能用作构造器(constructor)。不能用 new 调用它们。

箭头函数 VS bind

箭头函数 => 和使用 .bind(this) 调用的常规函数之间有细微的差别:

  • .bind(this) 创建了一个该函数的“绑定版本”。
  • 箭头函数 => 没有创建任何绑定。箭头函数只是没有 thisthis 的查找与常规变量的搜索方式完全相同:在外部词法环境中查找。

二、箭头函数没有 “arguments”

箭头函数也没有 arguments 变量。

当我们需要使用当前的 thisarguments 转发一个调用时,这对装饰器(decorators)来说非常有用。

例如,defer(f, ms) 获得了一个函数,并返回一个包装器,该包装器将调用延迟 ms 毫秒:

function defer(f, ms) {
  return function() {
    setTimeout(() => f.apply(this, arguments), ms)
  };
}

function sayHi(who) {
  alert('Hello, ' + who);
}

let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // 2 秒后显示:Hello, John

不用箭头函数的话,可以这么写:

function defer(f, ms) {
  return function(...args) {
    let ctx = this;
    setTimeout(function() {
      return f.apply(ctx, args);
    }, ms);
  };
}

在这里,我们必须创建额外的变量 argsctx,以便 setTimeout 内部的函数可以获取它们。

三、总结

箭头函数:

  • 没有 this
  • 没有 arguments
  • 不能使用 new 进行调用
  • 它们也没有 super,但目前我们还没有学到它。我们将在 类继承 一章中学习它。

这是因为,箭头函数是针对那些没有自己的“上下文”,但在当前上下文中起作用的短代码的。并且箭头函数确实在这种使用场景中大放异彩。

ES6标准新增了一种新的函数:Arrow Function(箭头函数)。为什么叫Arrow Function?

因为它的定义用的就是一个箭头:

x => x * x

示例相当于如下代码:

function (x) {
    return x * x;
}

JavaScript箭头函数是ECMAScript 6中引入的编写函数表达式的一种简便方法。

箭头函数的语法如下:

(parameters) => { statements }

如果没有参数,则表示一个箭头函数,如下所示:

() => { statements }

当您只有一个参数时,左括号是可选的:

parameters => { statements }

如果包含只返回返回表达式,请删除方括号:

parameters => expression


带来的好处

简洁的语法

让我们看一下常规函数:

function funcName(params) { 
  return params + 2; 
}
funcName(2); // 4

然后通过箭头函数精简之后为:

var funcName=params => params+2;
funcName(2); // 4

可以看到通过箭头函数实现之后,语法更加精简。

不绑定this

与常规函数不同,箭头函数不绑定this。相反,它是在词汇上绑定的(即this保持其原始上下文的含义)。

由于JavaScript函数对this绑定的错误处理,下面的例子无法得到预期结果:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function () {
            return 2020 - this.birth; // this指向window或undefined
        };
        return fn();
    }
};

但是,箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => 2020 - this.birth; // this指向obj对象
        return fn();
    }
};
obj.getAge(); // 30

使用箭头函数的限制条件

应用箭头函数时要注意的一些限制条件:

  • 箭头函数没有参数对象。
  • 箭头函数不能与新运算符一起使用,因此它不能用作构造函数。
  • 箭头函数没有原型属性。
  • 如果你尝试使用箭头函数作为构造函数,那么你会得到异常。请看下面的代码:

    var foo = (name, age) => { name = name, age = age };
    var f1 = new foo("cat", 6);

    代码试图通过使用箭头函数foo作为构造函数来创建对象f1,JavaScript将抛出以下异常:

    而且,当你试图输出箭头函数的原型值时,你会得到undefined的输出:

    var foo = (name, age) => { name = name, age = age };
    console.log(foo.prototype);

    发生这种情况的原因是因为箭头函数没有原型属性。请记住:虽然箭头函数为你提供了编写函数表达式的简短方法,但它没有自己的this值,也不能用作构造函数。

    在React中,事件处理函数是与用户交互的关键点,而向这些函数传递参数则是实现复杂逻辑和状态更新的基础。无论是使用箭头函数还是bind方法,正确地传递参数对于构建响应式和动态的用户界面至关重要。本文将深入探讨这两种方法的优劣,通过示例代码和解析,帮助你做出更合适的选择。

    箭头函数传参

    箭头函数是ES6引入的一种简洁的函数定义方式,它在React事件处理中特别受欢迎,因为它自动绑定this到当前上下文,消除了额外绑定的需要。此外,箭头函数非常适合用于立即执行的事件处理器,特别是当你需要在调用时传递参数时。

    示例代码

    1import React, { Component } from 'react';
    2
    3class ItemList extends Component {
    4  deleteItem = (index) => {
    5    console.log(`Deleting item at index ${index}`);
    6    // 进行删除逻辑
    7  };
    8
    9  render() {
    10    return (
    11      <div>
    12        {/* 假设items是一个数组 */}
    13        {this.props.items.map((item, index) => (
    14          <div key={index}>
    15            {item.name}
    16            <button onClick={() => this.deleteItem(index)}>
    17              Delete
    18            </button>
    19          </div>
    20        ))}
    21      </div>
    22    );
    23  }
    24}
    25
    26export default ItemList;

    在上述代码中,我们为每个<button>元素绑定了一个箭头函数,该函数在调用时接收index作为参数。这种方法的主要优点是它保持了代码的简洁性和可读性,同时避免了this绑定的问题。

    使用bind方法传参

    bind方法是JavaScript原生提供的一种函数方法,用于创建一个新的函数,其中this被绑定到给定的对象,任何额外的参数都会作为新函数的参数被预置。在React中,你也可以使用bind方法来为事件处理函数传递参数。

    示例代码

    import React, { Component } from 'react';
    
    class ItemList extends Component {
      deleteItem = (index) => {
        console.log(`Deleting item at index ${index}`);
        // 进行删除逻辑
      };
    
      render() {
        return (
          <div>
            {/* 假设items是一个数组 */}
            {this.props.items.map((item, index) => (
              <div key={index}>
                {item.name}
                <button onClick={this.deleteItem.bind(this, index)}>
                  Delete
                </button>
              </div>
            ))}
          </div>
        );
      }
    }
    
    export default ItemList;

    尽管使用bind方法可以有效地传递参数,但它在每次渲染时都会创建一个新的函数实例,这可能导致不必要的性能开销,尤其是在处理大量元素时。

    性能考量与最佳实践

    虽然箭头函数和bind方法都可以用来在事件处理器中传递参数,但箭头函数通常被认为是更好的选择,原因如下:

    1. 性能:箭头函数不会在每次渲染时创建新的函数实例,这有助于减少不必要的重渲染,提高应用性能。
    2. 简洁性:箭头函数的语法更加简洁,使代码更具可读性。
    3. this绑定:箭头函数自动绑定this到定义它的上下文,避免了额外的绑定操作。

    结语

    在React中,选择正确的事件处理方法和参数传递策略对于构建高效、可维护的应用程序至关重要。通过理解箭头函数和bind方法的差异,你可以根据具体场景选择最合适的方案。在大多数情况下,箭头函数因其简洁性和性能优势而成为首选。然而,根据项目的具体需求,bind方法在某些特定场景下也可能是一个合理的备选方案。

    通过本文的探讨,你不仅掌握了如何在React事件处理中有效传递参数,还对箭头函数和bind方法的优劣有了更深刻的认识。在未来的开发实践中,记得综合考虑性能、可读性和维护性,选择最适合你项目的技术方案。

    #头条创作挑战赛#