JavaScript中"=>"(由等号和大于号组成的箭头)是什么意思?

513
我知道>=运算符的意思是大于或等于,但我在一些源代码中看到了=>。那个运算符的含义是什么?
以下是代码:
promiseTargetFile(fpParams, aSkipPrompt, relatedURI).then(aDialogAccepted => {
    if (!aDialogAccepted)
        return;

    saveAsType = fpParams.saveAsType;
    file = fpParams.file;

    continueSave();
}).then(null, Components.utils.reportError);

5
请查看此链接有关箭头函数的信息。 - Mistalis
14个回答

621

是什么

这是一个箭头函数。 箭头函数是 ECMAscript 6 引入的一种简短语法,可以类似于函数表达式的方式使用。换句话说,您通常可以将它们用于替换诸如 function (foo) {...} 这样的表达式。但是它们有一些重要的区别。例如,它们不绑定自己的 this 值(请参见下面的讨论)。

箭头函数是 ECMAscript 6 规范的一部分。它们尚未在所有浏览器中得到支持,但在大多数现代浏览器中已被部分或完全支持 在 Node v. 4.0+ 中。 (我在下面包含了支持的浏览器的部分列表)。

您可以阅读 Mozilla 文档 上关于箭头函数的更多信息

来自 Mozilla 文档:

箭头函数表达式(也称为fat arrow函数)与函数表达式相比具有更短的语法,并在词法上绑定this值(不绑定自己的thisargumentssuper或者new.target)。箭头函数始终是匿名的。这些函数表达式最适合于非方法函数,并且它们不能用作构造函数。
关于箭头函数中this如何工作的说明

箭头函数最方便的功能之一被隐藏在上面的文本中:

箭头函数... 词法绑定 this 值(不绑定自己的 this...)

这意味着,简单来说,箭头函数保留了其上下文的 this 值,而没有自己的 this。传统函数可能会绑定它自己的 this 值,具体取决于如何定义和调用它。这可能需要进行很多花招,比如 self = this; 等等,才能从一个函数内部访问或操作另一个函数中的 this。关于此主题的更多信息,请参见 Mozilla 文档中的解释和示例

示例代码

示例(也来自文档):

var a = [
  "We're up all night 'til the sun",
  "We're up all night to get some",
  "We're up all night for good fun",
  "We're up all night to get lucky"
];

// These two assignments are equivalent:

// Old-school:
var a2 = a.map(function(s){ return s.length });

// ECMAscript 6 using arrow functions
var a3 = a.map( s => s.length );

// both a2 and a3 will be equal to [31, 30, 31, 31]

兼容性说明

在Node中可以使用箭头函数,但浏览器支持不够完善。

虽然浏览器对此功能的支持已经有所改善,但对于大多数基于浏览器的用途来说,仍不够普及。截至2017年12月12日,以下版本支持该功能:

  • Chrome(v. 45+)
  • Firefox(v. 22+)
  • Edge(v. 12+)
  • Opera(v. 32+)
  • Android Browser(v. 47+)
  • Opera Mobile(v. 33+)
  • Chrome for Android(v. 47+)
  • Firefox for Android(v. 44+)
  • Safari(v. 10+)
  • iOS Safari(v. 10.2+)
  • Samsung Internet(v. 5+)
  • Baidu Browser(v. 7.12+)

不支持的浏览器:

  • IE浏览器(通过版本11)
  • Opera Mini(通过版本8.0)
  • Blackberry浏览器(通过版本10)
  • IE移动版(通过版本11)
  • Android平台的UC浏览器(通过版本11.4)
  • QQ浏览器(通过版本1.2)

您可以在CanIUse.com上找到更多(和更为当前)的信息(无任何关联)。


4
TypeScript 似乎也支持它。 - mtyson
1
这看起来像是一个lambda表达式,对吗? - Addem
1
想提一下关于浏览器兼容性的问题,我使用ES6/ES7箭头函数和其他IE11原生不支持的特性,但是我使用Gulp或Webpack以及Babel将ES6转译为ES5,这样就可以在IE11中运行了。所以如果你需要支持IE11并且不介意设置Babel,那就去试试吧。 - mbokil
今天,所有现代浏览器都支持它们。 - Donald Duck
@DonaldDuck 是的,但该页面还显示并非所有用户都在使用现代浏览器。约有96.2%的用户使用支持箭头函数的浏览器,但这并非100%。根据上下文而定,这3.8%可能是一个避免某一语言特性的好理由,也可能不是。(别误会,就我个人而言,我认为这已经足够接近并覆盖了所有合法用户。但你的情况可能有所不同。) - elixenide

88
那被称为箭头函数,是ECMAScript 2015规范的一部分...

var foo = ['a', 'ab', 'abc'];

var bar = foo.map(f => f.length);

console.log(bar); // 1,2,3

比之前更短的语法:

// < ES6:
var foo = ['a', 'ab', 'abc'];

var bar = foo.map(function(f) {
  return f.length;
});
console.log(bar); // 1,2,3

演示

另一个很棒的东西是词法this...通常,您会这样做:

function Foo() {
  this.name = name;
  this.count = 0;
  this.startCounting();
}

Foo.prototype.startCounting = function() {
  var self = this;
  setInterval(function() {
    // this is the Window, not Foo {}, as you might expect
    console.log(this); // [object Window]
    // that's why we reassign this to self before setInterval()
    console.log(self.count);
    self.count++;
  }, 1000)
}

new Foo();

但是可以使用箭头来重写它,就像这样:

function Foo() {
  this.name = name;
  this.count = 0;
  this.startCounting();
}

Foo.prototype.startCounting = function() {
  setInterval(() => {
    console.log(this); // [object Object]
    console.log(this.count); // 1, 2, 3
    this.count++;
  }, 1000)
}

new Foo();

演示

MDN
更多语法信息

如果想了解更多,这里有一个非常好的关于何时使用箭头函数的答案。


1
最好将演示更新为使用https://esfiddle.net/,因为https://es6fiddle.net/不再可用。 - Wavesailor

29

这是箭头函数

也称为胖箭头函数,它们是一种干净简洁的编写函数表达式的方式,例如function() {}

箭头函数可以在定义函数时省略functionreturn{},它们是一行代码,类似于Java或Python中的Lambda表达式。

不带参数的示例

const queue = ['Dave', 'Sarah', 'Sharon'];
const nextCustomer = () => queue[0];

console.log(nextCustomer()); // 'Dave'

如果在同一箭头函数中需要进行多个语句的操作,你需要用大括号{}queue[0]包裹起来。在这种情况下,返回语句不能被省略。

带一个参数的示例

const queue = ['Dave', 'Sarah', 'Sharon'];
const addCustomer = name => {
  queue.push(name);
};

addCustomer('Toby');

console.log(queue); // ['Dave', 'Sarah', 'Sharon', 'Toby']

您可以从上面省略 {}

当只有一个参数时,可以省略围绕该参数的括号 ()

具有多个参数的示例

const addNumbers = (x, y) => x + y

console.log(addNumbers(1, 5)); // 6

一个有用的例子

const fruits = [
    { name: 'Apple', price: 2 },
    { name: 'Bananna', price: 3 },
    { name: 'Pear', price: 1 }
];

如果我们想在一个数组中获取每种水果的价格,在 ES5 中我们可以这样做:

fruits.map(function(fruit) {
    return fruit.price;
}); // [2, 3, 1]

在ES6中,使用新的箭头函数语法,我们可以使这个代码更加简洁:

fruits.map(fruit => fruit.price); // [2, 3, 1]

有关箭头函数的其他信息可以在这里找到。


25

1
请在内容中包含足够的信息,以便大多数读者不必深入了解? - djechlin
2
我所链接的维基百科非常简洁地描述了它的含义:“箭头函数表达式与函数表达式相比具有更短的语法,并在词法上绑定this值。箭头函数始终是匿名的。” - Kyle Falconer
1
将其作为引用添加到这里,将真正有助于您的答案。 - Hanky Panky

22

只是为了举例说明,在不使用map的情况下,lambda可以做的另一个示例:

a = 10
b = 2

var mixed = (a,b) => a * b; 
// OR
var mixed = (a,b) => { (any logic); return a * b };

console.log(mixed(a,b)) 
// 20

14

正如其他人所说,这是一种创建函数的新语法。

然而,这种函数与普通函数不同:

  • 它们绑定了 this 值。正如规范中解释的那样,

    箭头函数 不会为 argumentssuperthisnew.target 定义局部绑定。在 箭头函数 中对 argumentssuperthisnew.target 的任何引用都必须解析为词法封闭环境中的绑定。通常情况下,这将是立即包含函数的函数环境。

    即使 箭头函数 可能包含对 super 的引用,第 4 步中创建的函数对象也不会通过执行MakeMethod而成为方法。引用 super箭头函数 总是包含在非 箭头函数 中,实现 super 所需的状态可通过 箭头函数 的函数对象捕获的范围访问。

  • 它们不能用于构造函数。

    这意味着它们没有 [[Construct]] 内部方法,因此不能被实例化,例如:

    var f = a => a;
    f(123);  // 123
    new f(); // TypeError: f is not a constructor
    

9

对其他回答不满意。截止2019/3/13,得票最高的回答在事实上是错误的。

=> 的简短版本是它是一种快捷方式,用于编写一个函数并将其绑定到当前的this

const foo = a => a * 2;

实际上是一个快捷方式

const foo = function(a) { return a * 2; }.bind(this);

你可以看到所有被缩短的东西,我们不需要function,也不需要return,也不需要.bind(this),甚至不需要大括号或圆括号。
一个稍微更长的箭头函数示例可能是:
const foo = (width, height) => {
  const area = width * height;
  return area;
};

展示了如果我们想要函数有多个参数,需要使用括号,如果我们想要写多个表达式,需要用大括号和明确的 return

理解 .bind 的部分非常重要,它是一个大主题。这与 JavaScript 中 this 的含义有关。

全部 函数都有一个隐含的参数叫做 this。当调用一个函数时,如何设置 this 取决于该函数被调用的方式。

举个例子:

function foo() { console.log(this); }

如果您正常调用它
function foo() { console.log(this); }
foo();

this将成为全局对象。

如果您处于严格模式

`use strict`;
function foo() { console.log(this); }
foo();

// or

function foo() {
   `use strict`;
   console.log(this);
 }
foo();

这将会是未定义的

您可以使用callapply直接设置this

function foo(msg) { console.log(msg, this); }

const obj1 = {abc: 123}
const obj2 = {def: 456}

foo.call(obj1, 'hello');  // prints Hello {abc: 123}
foo.apply(obj2, ['hi']);  // prints Hi {def: 456}

你也可以使用点运算符.隐式地设置this

function foo(msg) { console.log(msg, this); }
const obj = {
   abc: 123,
   bar: foo,
}
obj.bar('Hola');  // prints Hola {abc:123, bar: f}

当你想将一个函数作为回调或监听器使用时,就会出现一个问题。你创建了一个类,并希望将一个函数指定为回调,以便访问该类的一个实例。

class ShowName {
  constructor(name, elem) {
    this.name = name;
    elem.addEventListener('click', function() {
       console.log(this.name);  // won't work
    }); 
  }
}

上述代码无法正常工作,因为当元素触发事件并调用函数时,this值将不是类的实例。解决该问题的一种常见方法是使用.bind
class ShowName {
  constructor(name, elem) {
    this.name = name;
    elem.addEventListener('click', function() {
       console.log(this.name); 
    }.bind(this); // <=========== ADDED! ===========
  }
}

因为箭头语法执行的是相同的操作,所以我们可以写成:

因为箭头语法执行的是相同的操作,所以我们可以这样写:

class ShowName {
  constructor(name, elem) {
    this.name = name;
    elem.addEventListener('click',() => {
       console.log(this.name); 
    });
  }
}

bind 实际上会创建一个新的函数。如果没有 bind,你可以像这样自己创建:

function bind(functionToBind, valueToUseForThis) {
  return function(...args) {
    functionToBind.call(valueToUseForThis, ...args);
  };
}

在没有展开运算符的旧版JavaScript中,它会是这样的:
function bind(functionToBind, valueToUseForThis) {
  return function() {
    functionToBind.apply(valueToUseForThis, arguments);
  };
}

了解代码需要理解闭包,但简单来说,bind会创建一个新函数,该函数始终使用绑定到它的this值调用原始函数。由于箭头函数是bind(this)的快捷方式,因此它们也会执行同样的操作。


8
我会尽力帮助您进行翻译。以下是您需要翻译的内容:

我已经阅读过,这是ES6中箭头函数的符号

这个

var a2 = a.map(function(s){ return s.length });

使用箭头函数可写成:
var a3 = a.map( s => s.length );

{{链接1:MDN文档}}


7
箭头函数(用符号(=>)表示)有助于创建匿名函数和方法。这导致更短的语法。例如,下面是一个简单的“添加”函数,它返回两个数字的加法。
function Add(num1 , num2 ){
return num1 + num2;
}

上述函数可以使用“箭头”语法缩短,如下所示。 enter image description here 以上代码分为两个部分,如上图所示:
输入:-此部分指定匿名函数的输入参数。
逻辑:此部分出现在符号“=>”之后。此部分具有实际函数的逻辑。
许多开发人员认为箭头函数使您的语法更简短,更简单,因此使您的代码更易读。
如果您相信上面的话,那么让我向您保证这是一个神话。如果您想一想,一个正确编写了名称的函数比使用箭头符号创建的加密函数更易读。
箭头函数的主要用途是确保代码在调用者上下文中运行。
请参见下面的代码,其中定义了全局变量“context”,该全局变量在从其他方法“SomeMethod”调用的函数“SomeOtherMethod”内被访问。
此“SomeMethod”具有本地“context”变量。现在,因为我们从“SomeMethod”调用了“SomeOtherMethod”,所以我们希望它显示“local context”,但它显示“global context”。
var context = “global context”;

function SomeOtherMethod(){
alert(this.context);
}

function SomeMethod(){
this.context = “local context”;
SomeOtherMethod();
}

var instance = new SomeMethod();

但是如果使用箭头函数替换调用,它将显示 "local context"。

var context = "global context";
   
    function SomeMethod(){
        this.context = "local context";
        SomeOtherMethod = () => {
            alert(this.context);
        }
        SomeOtherMethod();
    }
    var instance = new SomeMethod();

我建议您阅读此链接(JavaScript中的箭头函数),其中讲解了JavaScript上下文的所有情况,以及在哪些情况下不会尊重调用方的上下文。
您还可以在我制作的这个YouTube视频中看到JavaScript中箭头函数的演示,它实际演示了术语“上下文”。

1
其中一个更好的答案。虽然我会从句子“=>是一种更简短的编写函数的方式,它接受一些参数(在左侧),然后对其进行某些操作(在右侧)”开始。 - Reddspark

6

使用箭头函数添加简单的CRUD示例

 //Arrow Function
 var customers   = [
   {
     name: 'Dave',
     contact:'9192631770'
   },
   {
     name: 'Sarah',
     contact:'9192631770'
   },
   {
     name: 'Akhil',
     contact:'9928462656' 
   }],

// No Param READ
 getFirstCustomer = () => { 
   console.log(this);
   return customers[0];
 };
  console.log("First Customer "+JSON.stringify(getFirstCustomer())); // 'Dave' 

   //1 Param SEARCH
  getNthCustomer = index=>{
    if( index>customers.length)
    {
     return  "No such thing";
   }
   else{
       return customers[index];
     } 
  };
  console.log("Nth Customer is " +JSON.stringify(getNthCustomer(1))); 

   //2params ADD
  addCustomer = (name, contact)=> customers.push({
     'name': name,
     'contact':contact
    });
  addCustomer('Hitesh','8888813275');
  console.log("Added Customer "+JSON.stringify(customers)); 

  //2 param UPDATE
  updateCustomerName = (index, newName)=>{customers[index].name= newName};
  updateCustomerName(customers.length-1,"HiteshSahu");
  console.log("Updated Customer "+JSON.stringify(customers));

  //1 param DELETE
  removeCustomer = (customerToRemove) => customers.pop(customerToRemove);
  removeCustomer(getFirstCustomer());
  console.log("Removed Customer "+JSON.stringify(customers)); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接