Ý nghĩa của những gì về = = mệnh (một mũi tên được hình thành từ bằng & lớn hơn) trong JavaScript?


444

Tôi biết rằng >=toán tử có nghĩa nhiều hơn hoặc bằng, nhưng tôi đã thấy =>trong một số mã nguồn. Ý nghĩa của toán tử đó là gì?

Đây là mã:

promiseTargetFile(fpParams, aSkipPrompt, relatedURI).then(aDialogAccepted => {
    if (!aDialogAccepted)
        return;

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

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

5
Xem liên kết này về các chức năng mũi tên .
Mistalis

Câu trả lời:


546

Nó là gì

Đây là một chức năng mũi tên. Các hàm mũi tên là một cú pháp ngắn, được giới thiệu bởi ECMAscript 6, có thể được sử dụng tương tự như cách bạn sẽ sử dụng các biểu thức hàm. Nói cách khác, bạn thường có thể sử dụng chúng thay cho biểu thức như thế nào function (foo) {...}. Nhưng họ có một số khác biệt quan trọng. Ví dụ, họ không ràng buộc các giá trị riêng của họ this(xem bên dưới để thảo luận).

Các hàm mũi tên là một phần của đặc tả ECMAscript 6. Chúng chưa được hỗ trợ trong tất cả các trình duyệt, nhưng chúng được hỗ trợ một phần hoặc toàn bộ trong Node v. 4.0+ và trong hầu hết các trình duyệt hiện đại được sử dụng kể từ năm 2018. (Tôi đã bao gồm một danh sách một phần các trình duyệt hỗ trợ bên dưới).

Bạn có thể đọc thêm trong tài liệu Mozilla về các chức năng mũi tên .

Từ tài liệu Mozilla:

Một biểu hiện mũi tên chức năng (còn gọi là mũi tên chức năng chất béo) có một cú pháp ngắn hơn so với biểu hiện chức năng và giải nghĩa từ vựng liên kết với các thisgiá trị (không ràng buộc riêng của mình this, arguments, super, hoặc new.target). Các chức năng mũi tên luôn ẩn danh. Các biểu thức hàm này phù hợp nhất cho các hàm phi phương thức và chúng không thể được sử dụng làm hàm tạo.

Lưu ý về cách thức thishoạt động của các chức năng mũi tên

Một trong những tính năng tiện dụng nhất của chức năng mũi tên được chôn trong văn bản trên:

Hàm mũi tên ... liên kết từ vựng theo thisgiá trị (không ràng buộc giá trị của nó this...)

Điều này có nghĩa đơn giản là hàm mũi tên giữ lại thisgiá trị từ ngữ cảnh của nó và không có giá trị riêng this. Một hàm truyền thống có thể liên kết thisgiá trị riêng của nó , tùy thuộc vào cách nó được định nghĩa và gọi. Điều này có thể yêu cầu rất nhiều môn thể dục như self = this;, v.v., để truy cập hoặc thao tác thistừ một chức năng bên trong chức năng khác. Để biết thêm thông tin về chủ đề này, hãy xem phần giải thích và ví dụ trong tài liệu Mozilla .

Mã ví dụ

Ví dụ (cũng từ các tài liệu):

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]

Ghi chú về Tương thích

Bạn có thể sử dụng các chức năng mũi tên trong Node, nhưng hỗ trợ trình duyệt là không chính xác.

Hỗ trợ trình duyệt cho chức năng này đã được cải thiện khá nhiều, nhưng nó vẫn chưa đủ rộng cho hầu hết các ứng dụng dựa trên trình duyệt. Kể từ ngày 12 tháng 12 năm 2017, nó được hỗ trợ trong các phiên bản hiện tại của:

  • Chrome (câu 45+)
  • Firefox (câu 22+)
  • Cạnh (câu 12+)
  • Opera (câu 32+)
  • Trình duyệt Android (câu 47+)
  • Opera Mobile (câu 33+)
  • Chrome dành cho Android (câu 47+)
  • Firefox cho Android (câu 44+)
  • Safari (câu 10+)
  • Safari Safari (phiên bản 10.2 trở lên)
  • Internet Samsung (câu 5+)
  • Trình duyệt Yahoo (v. 7.12+)

Không được hỗ trợ trong:

  • IE (đến câu 11)
  • Opera Mini (đến câu 8.0)
  • Trình duyệt Blackberry (đến câu 10)
  • IE Mobile (đến câu 11)
  • UC Browser cho Android (đến câu 11.4)
  • QQ (đến câu 1.2)

Bạn có thể tìm thêm thông tin (và hiện tại) tại CanIUse.com (không liên kết).


3
TypeScript dường như cũng hỗ trợ nó.
mtyson

1
Có vẻ như đây là một biểu hiện lambda, phải không?
Bổ sung

1
Muốn đề cập đến khả năng tương thích trình duyệt, tôi sử dụng các chức năng mũi tên ES6 / ES7 và các tính năng khác không tương thích với IE11 nhưng tôi sử dụng Gulp hoặc Webpack cùng với Babel để dịch mã ES6 sang ES5 để nó hoạt động trong IE11. Vì vậy, nếu bạn cần hỗ trợ IE11 và bạn không ngại thiết lập Babel thì hãy thực hiện.
mbokil

76

Đó được gọi là Chức năng Mũi tên, một phần của thông số ECMAScript 2015 ...

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

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

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

Cú pháp ngắn hơn so với trước:

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

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

BẢN GIỚI THIỆU

Một điều tuyệt vời khác là từ vựng this ... Thông thường, bạn sẽ làm một cái gì đó như:

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();

Nhưng điều đó có thể được viết lại bằng mũi tên như thế này:

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();

BẢN GIỚI THIỆU

MDN
Thêm về Cú pháp

Để biết thêm, đây là một câu trả lời khá hay khi sử dụng các hàm mũi tên.


Sẽ tốt hơn nếu cập nhật các bản demo để sử dụng esfiddle.netes6fiddle.net không còn hoạt động
Wavesailor

25

Đây sẽ là "biểu thức hàm mũi tên" được giới thiệu trong ECMAScript 6.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/arrow_fifts

Đối với mục đích lịch sử (nếu trang wiki thay đổi sau này), đó là:

Biểu thức hàm mũi tên có cú pháp ngắn hơn so với biểu thức hàm và liên kết từ vựng với giá trị này. Các chức năng mũi tên luôn ẩn danh.


1
Tâm trí bao gồm đủ thông tin để hầu hết độc giả không phải đi sâu vào?
djechlin

2
Wiki tôi liên kết với mô tả rất ngắn gọn: "Biểu thức hàm mũi tên có cú pháp ngắn hơn so với biểu thức hàm và liên kết từ vựng với giá trị này. Hàm mũi tên luôn ẩn danh."
Kyle Falconer

1
Thêm vào đó như một trích dẫn ở đây sẽ thực sự giúp câu trả lời của bạn.
Hanky ​​Panky

22

Đây là các hàm mũi tên

Còn được gọi là Chức năng Mũi tên Chất béo . Chúng là một cách rõ ràng và hợp lý để viết các biểu thức hàm, vd function() {}.

Chức năng mũi tên có thể loại bỏ sự cần thiết của function, return{}khi xác định các chức năng. Chúng là các lớp lót, tương tự như Biểu thức Lambda trong Java hoặc Python.

Ví dụ không có tham số

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

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

Nếu nhiều câu lệnh cần được thực hiện trong cùng một Hàm mũi tên, bạn cần phải bọc, trong ví dụ này, queue[0]trong dấu ngoặc nhọn {}. Trong trường hợp này, câu lệnh return không thể được bỏ qua.

Ví dụ với 1 tham số

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

addCustomer('Toby');

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

Bạn có thể bỏ qua {}từ trên.

Khi có một tham số duy nhất, các dấu ngoặc ()quanh tham số có thể được bỏ qua.

Ví dụ với nhiều tham số

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

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

Một ví dụ hữu ích

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

Nếu chúng ta muốn lấy giá của mỗi loại trái cây trong một mảng duy nhất, trong ES5 chúng ta có thể làm:

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

Trong ES6 với các Hàm mũi tên mới, chúng ta có thể làm cho điều này ngắn gọn hơn:

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

Thông tin bổ sung về Chức năng Mũi tên có thể được tìm thấy ở đây .

tính tương thích của trình duyệt web

  • IE: Chưa được hỗ trợ
  • Cạnh: 12+ (Tất cả các phiên bản)
  • Firefox: 22+
  • Chrome: 45+
  • Safari: 10+
  • Safari Safari: 10.2+
  • Trình duyệt Android: 56+

Thông tin cập nhật bổ sung có thể được tìm thấy về khả năng tương thích trình duyệt tại đây


21

chỉ để thêm một ví dụ khác về những gì lambda có thể làm mà không cần sử dụng bản đồ:

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

13

Như những người khác đã nói, đó là một cú pháp mới để tạo chức năng.

Tuy nhiên, loại chức năng này khác với chức năng bình thường:

  • Họ ràng buộc thisgiá trị. Theo giải thích của thông số kỹ thuật ,

    Một ArrowFunction không định nghĩa các ràng buộc địa phương arguments, super, this, hoặc new.target. Bất kỳ tài liệu tham khảo để arguments, super, this, hoặc new.targettrong một ArrowFunction phải giải quyết đến một ràng buộc trong một môi trường giải nghĩa từ vựng kèm theo. Thông thường, đây sẽ là Môi trường chức năng của một chức năng kèm theo ngay lập tức.

    Mặc dù Mũi tên có thể chứa các tham chiếu đến super, đối tượng hàm được tạo trong bước 4 không được tạo thành phương thức bằng cách thực hiện MakeMethod . Một ArrowFunction mà các tham chiếu super luôn được chứa trong một Hàm không phải là Mũi tên và trạng thái cần thiết để thực hiện supercó thể truy cập được thông qua phạm vi được bắt bởi đối tượng chức năng của Mũi tên .

  • Họ không phải là người xây dựng.

    Điều đó có nghĩa là họ không có phương thức nội bộ [[Xây dựng]] và do đó không thể khởi tạo được, ví dụ:

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

8

Tôi đã đọc, đây là một biểu tượng của sự Arrow FunctionstrongES6

điều này

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

sử dụng Arrow Functioncó thể được viết là

var a3 = a.map( s => s.length );

Tài liệu MDN


6

Thêm ví dụ CRUD đơn giản với Mũi tên

 //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)); 

4

Không hài lòng với các câu trả lời khác. Câu trả lời được bình chọn hàng đầu vào năm 2019/3/13 là thực tế sai.

Phiên bản ngắn gọn của ý =>nghĩa của nó là một phím tắt viết một hàm để ràng buộc nó với hiện tạithis

const foo = a => a * 2;

Đây có phải là một lối tắt cho

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

Bạn có thể thấy tất cả những điều đã được rút ngắn. Chúng tôi không cần function, cũng không phải returnvà cũng không .bind(this)hay thậm chí niềng răng hoặc ngoặc

Một ví dụ dài hơn một chút về chức năng mũi tên có thể là

const foo = (width, height) => {
  const area = width * height;
  return area;
};

Cho thấy rằng nếu chúng ta muốn có nhiều đối số cho hàm, chúng ta cần dấu ngoặc đơn và nếu chúng ta muốn viết nhiều hơn một biểu thức, chúng ta cần dấu ngoặc và một hàm rõ ràng return.

Điều quan trọng là phải hiểu .bindmột phần và đó là một chủ đề lớn. Nó phải làm với những gì thiscó nghĩa là trong JavaScript.

TẤT CẢ các hàm có một tham số ngầm gọi là this. Cách thisđặt khi gọi hàm phụ thuộc vào cách gọi hàm đó.

Lấy

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

Nếu bạn gọi nó bình thường

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

this sẽ là đối tượng toàn cầu.

Nếu bạn đang ở chế độ nghiêm ngặt

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

// or

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

Nó sẽ là undefined

Bạn có thể đặt thistrực tiếp bằng callhoặcapply

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}

Bạn cũng có thể đặt thisngầm sử dụng toán tử dấu chấm.

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

Một vấn đề xuất hiện khi bạn muốn sử dụng một chức năng như một cuộc gọi lại hoặc một người nghe. Bạn tạo lớp và muốn gán một hàm làm hàm gọi lại truy cập một thể hiện của lớp.

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

Đoạn mã trên sẽ không hoạt động vì khi phần tử kích hoạt sự kiện và gọi hàm, thisgiá trị sẽ không phải là thể hiện của lớp.

Một cách phổ biến để giải quyết vấn đề đó là sử dụng .bind

class ShowName {
  constructor(name, elem) {
    this.name = name;
    elem.addEventListener('click', function() {
       console.log(this.name); 
    }.bind(this); // <=========== ADDED! ===========
  }
}

Bởi vì cú pháp mũi tên làm điều tương tự chúng ta có thể viết

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

bindcó hiệu quả làm cho một chức năng mới . Nếu bindkhông tồn tại, về cơ bản bạn có thể làm cho riêng mình như thế này

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

Trong JavaScript cũ hơn mà không có toán tử trải rộng, nó sẽ là

function bind(funcitonToBind, valueToUseForThis) {
  return function() {
    functionToBind.apply(valueToUseForThis, arguments);
  };
}

Hiểu mã đó đòi hỏi phải hiểu về các bao đóng nhưng phiên bản ngắn sẽ bindtạo ra một hàm mới luôn gọi hàm gốc với thisgiá trị được ràng buộc với nó. chức năng mũi tên làm điều tương tự vì chúng là một phím tắt chobind(this)


2

Như tất cả các câu trả lời khác đã nói, đó là một phần của cú pháp hàm mũi tên ES2015. Cụ thể hơn, đó không phải là một nhà điều hành, đó là mã thông báo dấu chấm câu tách biệt các tham số khỏi phần thân : ArrowFunction : ArrowParameters => ConciseBody. Ví dụ (params) => { /* body */ }.


1

ES6 Chức năng mũi tên:

Trong javascript, =>nó là biểu tượng của một biểu thức hàm mũi tên. Một biểu thức hàm mũi tên không có thisràng buộc riêng và do đó không thể được sử dụng làm hàm xây dựng. ví dụ:

var words = 'hi from outside object';

let obj = {
  words: 'hi from inside object',
  talk1: () => {console.log(this.words)},
  talk2: function () {console.log(this.words)}
}

obj.talk1();  // doesn't have its own this binding, this === window
obj.talk2();  // does have its own this binding, this is obj

Quy tắc sử dụng các chức năng mũi tên:

  • Nếu có chính xác một đối số, bạn có thể bỏ qua dấu ngoặc đơn của đối số.
  • Nếu bạn trả về một biểu thức và thực hiện điều này trên cùng một dòng, bạn có thể bỏ qua câu lệnh {}returncâu lệnh

Ví dụ:

let times2 = val => val * 2;  
// It is on the same line and returns an expression therefore the {} are ommited and the expression returns implictly
// there also is only one argument, therefore the parentheses around the argument are omitted

console.log(times2(3));


1

Các hàm mũi tên được biểu thị bằng ký hiệu (=>) giúp bạn tạo các hàm và phương thức ẩn danh. Điều đó dẫn đến cú pháp ngắn hơn. Ví dụ, bên dưới là một hàm Add Add đơn giản, trả về phép cộng hai số.

function Add(num1 , num2 ){
return num1 + num2;
}

Hàm trên trở nên ngắn hơn bằng cách sử dụng cú pháp của Arrow Arrow.

nhập mô tả hình ảnh ở đây

Mã trên có hai phần như thể hiện trong sơ đồ trên: -

Đầu vào: - Phần này chỉ định các tham số đầu vào cho chức năng ẩn danh.

Logic: - Phần này xuất hiện sau ký hiệu Nhận =>. Phần này có logic của chức năng thực tế.

Nhiều nhà phát triển nghĩ rằng hàm mũi tên làm cho cú pháp của bạn ngắn hơn, đơn giản hơn và do đó làm cho mã của bạn có thể đọc được.

Nếu bạn tin câu trên, thì hãy để tôi đảm bảo với bạn đó là chuyện hoang đường. Nếu bạn nghĩ rằng một hàm viết đúng với tên dễ đọc hơn các hàm mật mã được tạo trong một dòng bằng ký hiệu mũi tên.

Việc sử dụng chính của chức năng mũi tên là để đảm bảo mã chạy trong ngữ cảnh người gọi.

Xem đoạn mã dưới đây có biến "bối cảnh" toàn cầu được xác định, biến toàn cục này được truy cập bên trong một hàm "someOtherMethod" được gọi từ phương thức khác "someMethod".

"Một số" có một biến "bối cảnh" cục bộ. Bây giờ vì "someOtherMethod" được gọi từ "" someMethod ", chúng tôi hy vọng nó sẽ hiển thị" bối cảnh cục bộ ", nhưng nó hiển thị" bối cảnh toàn cầu ".

var context = global context”;

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

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

var instance = new SomeMethod();

Nhưng nếu thay thế cuộc gọi bằng chức năng Mũi tên, nó sẽ hiển thị "ngữ cảnh cục bộ".

var context = "global context";

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

Tôi khuyến khích bạn đọc liên kết này ( hàm Mũi tên trong JavaScript ) để giải thích tất cả các kịch bản của bối cảnh javascript và trong đó các kịch bản bối cảnh của người gọi không được tôn trọng.

Bạn cũng có thể xem trình diễn chức năng Mũi tên với javascript trong video youtube này thể hiện thực tế thuật ngữ Ngữ cảnh.


0

Như những người khác đã nêu, các hàm thông thường (truyền thống) sử dụng thistừ đối tượng được gọi là hàm, (ví dụ: một nút được nhấp) . Thay vào đó, các hàm mũi tên sử dụng thistừ đối tượng xác định hàm.

Hãy xem xét hai chức năng gần như giống hệt nhau:

regular = function() {
  ' Identical Part Here;
}


arrow = () => {
  ' Identical Part Here;
}

Đoạn mã dưới đây cho thấy sự khác biệt cơ bản giữa những gì thisđại diện cho từng chức năng. Các chức năng thường xuyên kết quả đầu ra [object HTMLButtonElement]trong khi mũi tên chức năng đầu ra [object Window].

<html>
 <button id="btn1">Regular: `this` comes from "this button"</button>
 <br><br>
 <button id="btn2">Arrow: `this` comes from object that defines the function</button>
 <p id="res"/>

 <script>
  regular = function() {
    document.getElementById("res").innerHTML = this;
  }

  arrow = () => {
    document.getElementById("res").innerHTML = this;
  }

  document.getElementById("btn1").addEventListener("click", regular);
  document.getElementById("btn2").addEventListener("click", arrow);
 </script>
</html>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.