了解JavaScript中的箭头功能表达式
#javascript #functions #es6 #arrowfunctions

根据最近的开发人员调查,JavaScript仍然是世界上最常用的编程语言,它仍然在全球各个组织的需求量很高。鉴于这一信息以及我喜欢写有关JavaScript的事实,我将花更多的时间和资源来编写有关该语言的优质内容。我们现在关注的话题是; 箭头功能 。不再浪费时间,让我们开始研究箭头功能的来龙去脉。但是在我们这样做之前,我希望我们对常规或传统的JS功能进行一些复活,以便将所有内容置于视角上。我们可以吗?

Functions是JavaScript中的基本构建块之一,它们基本上是旨在执行特定任务的代码块。要使用功能,您必须首先将其定义在您希望从中调用的范围中的某个位置。

function关键字定义或声明的函数。以下是JavaScript中函数的语法。

function nameOfFunction() {
    // Block of code to be executed
}

声明以function关键字开头,然后是函数的名称。在任何代码运行之前,功能声明加载到执行上下文中。这被称为hoisting,这意味着您可以在声明之前使用该功能。

定义函数的另一种方法是通过函数表达式,基本上将函数分配给变量。与函数声明不同,函数表达式未预加载到执行上下文中,只有在程序遇到它时运行。以下是计算两个数字总和的函数表达式的示例。

const sum = function (a, b) {
  return a + b
}

在定义之前试图调用此函数将导致错误。现在到箭头功能!

箭头功能

箭头函数从根本上是传统JS功能表达式的较短替代方法,其语义差异有一些差异,并且在其使用中有意限制。箭头函数始终是匿名的,无法命名箭头函数。在下一节中,您将探讨箭头功能和传统JavaScript函数之间的句法和实际差异。

箭头功能的行为和语法

箭头函数在使它们与传统JS功能不同以及一些句法增强功能中不同的工作方式上有一些重要区别。这些差异是:

  • 箭头功能没有自己与this的绑定
  • 箭头功能没有constructorprototype

现在让我们查看这些要点的详细含义。

箭头函数没有自己与this的绑定:箭头函数内部的上下文是词汇或静态定义的。这意味着,与常规的JS函数不同,箭头函数中的this的值不取决于它们的调用方式或定义方式。它仅取决于其封闭的上下文。这似乎有些混乱,所以让我们通过查看一个示例来理解它。在此示例中,我们将创建一个基本对象,并在JavaScript中查看对象的使用

let Student = function(student, age) {
        this.student = student;
        this.age = age;
        this.info = function() {

         // logs Student
         console.log(this);

         setTimeout(function() {
            // here this!=Student
           console.log(this.student + " is " + this.age + 
                                              " years old");
          }, 2000);
        }
    } 
 let student1 = new Student('James', 19);

    // logs : undefined is undefined years old after 3 seconds
    student1.info();

我们获得undefined值而不是正确的信息的原因是因为将function()定义为setTimeout()的回调是传统的JS函数,这意味着其上下文设置为全局上下文,换句话说, this设置为window对象。
之所以发生这种情况,是因为每个常规的JavaScript函数都根据其调用来定义自己的此或上下文。封闭对象或函数的上下文不会影响这种自动定义自己上下文的趋势。

现在我们如何解决这个问题?可能会想到的一个明显的解决方案是,如果该函数没有定义自己的此或上下文,该怎么办?如果它从info()继承了上下文,因为这意味着回调函数获取了info()
中定义的此功能 好吧,这正是箭头功能所做的。他们从封闭的上下文中保留this的价值。在上面的示例中,如果settimeout()中的回调函数是箭头函数,它将从其封闭的上下文中继承this的值 - info()

let Student = function(student, age) {
        this.student = student;
        this.age = age;
        this.info = function() {

            // logs Student
            console.log(this); 

           setTimeout(() => { 
            // arrow function to make lexical "this" binding
            // here this=Student."this" has been inherited
            console.log(this.student + " is " + this.age 
                                           + " years old");
           }, 2000);
        }
    } 
    let student1 = new Student('James', 19);

    // logs : James is 19 years old after 2 seconds
    student1.info();

箭头函数的this值与其封闭的上下文中的this的值相同,而this的值是立即之外的上下文。如果在外部使用任何封闭函数之外,则箭头函数继承了全局上下文,从而将this的值设置为全局窗口对象。

箭头函数在JavaScript,函数和类中没有constructorprototype具有prototype属性,它是克隆和inheritance的蓝图。为了证明这一点,创建一个函数并将自动分配的prototype属性记录到控制台:

function myFunction() {
  this.number = 8
}

// Log the prototype property of myFunction
console.log(myFunction.prototype)

这将在控制台上打印以下内容:

Output
{constructor: ƒ}

这表明在prototype属性中有一个带有constructor的对象。这使您可以使用new关键字来创建函数的实例:

const newInstance = new myFunction()

console.log(newInstance.value)

这将赋予您首次声明该函数时定义的number属性的值。相比之下,箭头功能没有prototype属性。创建一个箭头功能,并尝试将其prototype记录到控制台,您会发现您获得的输出是undefined。由于丢失的prototype属性,new关键字不可用,您无法构造箭头函数的实例。

除了箭头函数所表现出的这些差异外,还有一些可选的句法变化,使编写箭头功能更快,更少。下一节将显示这些语法更改的示例。

箭头功能隐式返回

众所周知,传统的JavaScript功能的主体使用Curly Brackets {}包含在一个块中,并在代码遇到return关键字时结束。以下是此实现的样子,如箭头函数:

const sum = (x, y) => {
  return x + y
}

箭头功能还允许省略return关键字和卷曲括号。发生这种情况时,会有隐式返回。

const sum = (a, b) => a + b

隐式返回对于在诸如mapfilter和其他常见数组方法等数组方法中创建简洁的单行操作很有用。请注意,必须省略括号和return关键字。如果您不能将尸体写为单线返回语句,则必须使用普通的块主体语法。

在返回对象的情况下,语法要求您将对象包裹在括号中,如下所示:

const sum = (a, b) => ({result: a + b})

sum(7, 2)

如果您不将对象封闭在括号中,则括号将被视为功能主体,并且不会计算返回值。

注意:如果您的箭头功能没有参数,则不应因为必需的括号而忽略括号。

结论

始终尝试记住常规JS功能和箭头功能之间的差异。正如我们刚刚看到的那样,它们在同一情况下的行为可能会有所不同。最好在callbacksclosures上使用箭头功能,因为它们的语法简洁明了。