Nhiều hàm mũi tên trong javascript nghĩa là gì?

522
jhamm 2015-09-26 03:06.

Tôi đã đọc một loạt reactmã và tôi thấy những thứ như thế này mà tôi không hiểu:

handleChange = field => e => {
  e.preventDefault();
  /// Do something here
}

7 answers

926
Thank you 2015-09-26 07:39.

Đó là một chức năng cà ri

Đầu tiên, hãy kiểm tra hàm này với hai tham số…

const add = (x, y) => x + y
add(2, 3) //=> 5

Đây lại là dạng cà ri…

const add = x => y => x + y

Đây là cùng 1 mã không có hàm mũi tên…

const add = function (x) {
  return function (y) {
    return x + y
  }
}

Tập trung vào return

Nó có thể hữu ích để hình dung nó theo cách khác. Chúng ta biết rằng các hàm mũi tên hoạt động như thế này - hãy đặc biệt chú ý đến giá trị trả về .

const f = someParam => returnValue

Vì vậy, addhàm của chúng ta trả về một hàm - chúng ta có thể sử dụng dấu ngoặc đơn để rõ ràng hơn. Các in đậm văn bản là giá trị trả về của hàm của chúng tôiadd

const add = x => (y => x + y)

Nói cách khác, addmột số số trả về một hàm

add(2) // returns (y => 2 + y)

Gọi các chức năng cà ri

Vì vậy, để sử dụng chức năng cà ri của chúng tôi, chúng tôi phải gọi nó khác một chút…

add(2)(3)  // returns 5

Điều này là do lệnh gọi hàm đầu tiên (bên ngoài) trả về hàm thứ hai (bên trong). Chỉ sau khi chúng ta gọi hàm thứ hai, chúng ta mới thực sự nhận được kết quả. Điều này rõ ràng hơn nếu chúng ta tách các cuộc gọi trên hai dòng…

const add2 = add(2) // returns function(y) { return 2 + y }
add2(3)             // returns 5

Áp dụng hiểu biết mới của chúng tôi vào mã của bạn

liên quan: "Sự khác biệt giữa ràng buộc, áp dụng một phần và cà ri là gì?"

Được rồi, bây giờ chúng tôi đã hiểu cách hoạt động của nó, hãy xem mã của bạn

handleChange = field => e => {
  e.preventDefault()
  /// Do something here
}

Chúng tôi sẽ bắt đầu bằng cách biểu diễn nó mà không sử dụng các hàm mũi tên…

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  };
};

Tuy nhiên, bởi vì các chức năng của mũi tên liên kết từ vựng this, nó thực sự sẽ trông giống như thế này…

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  }.bind(this)
}.bind(this)

Có lẽ bây giờ chúng ta có thể thấy điều này đang làm rõ ràng hơn. Các handleChangechức năng được tạo ra một chức năng cho một quy định field. Đây là một kỹ thuật React tiện dụng vì bạn phải thiết lập trình lắng nghe của riêng mình trên mỗi đầu vào để cập nhật trạng thái ứng dụng của bạn. Bằng cách sử dụng handleChangehàm, chúng ta có thể loại bỏ tất cả các mã trùng lặp dẫn đến việc thiết lập trình changelắng nghe cho mỗi trường. Mát mẻ!

1 Ở đây tôi không phải ràng buộc từ vựng thisaddhàm gốc không sử dụng bất kỳ ngữ cảnh nào, vì vậy không quan trọng để bảo toàn nó trong trường hợp này.


Nhiều mũi tên hơn nữa

Nhiều hơn hai hàm mũi tên có thể được sắp xếp theo trình tự, nếu cần -

const three = a => b => c =>
  a + b + c

const four = a => b => c => d =>
  a + b + c + d

three (1) (2) (3) // 6

four (1) (2) (3) (4) // 10

Các chức năng của Curry có khả năng tạo ra những điều đáng ngạc nhiên Dưới đây, chúng tôi thấy $được định nghĩa là một hàm có hai tham số, nhưng tại trang web cuộc gọi, nó xuất hiện như thể chúng tôi có thể cung cấp bất kỳ số lượng đối số nào. Currying là trừu tượng của arity -

const $ = x => k =>
  $ (k (x))
  
const add = x => y =>
  x + y

const mult = x => y =>
  x * y
  
$ (1)           // 1
  (add (2))     // + 2 = 3
  (mult (6))    // * 6 = 18
  (console.log) // 18
  
$ (7)            // 7
  (add (1))      // + 1 = 8
  (mult (8))     // * 8 = 64
  (mult (2))     // * 2 = 128
  (mult (2))     // * 2 = 256
  (console.log)  // 256

Ứng dụng một phần

Ứng dụng từng phần là một khái niệm liên quan. Nó cho phép chúng tôi áp dụng một phần các chức năng, tương tự như nấu cà ri, ngoại trừ chức năng không phải được xác định ở dạng cà ri -

const partial = (f, ...a) => (...b) =>
  f (...a, ...b)

const add3 = (x, y, z) =>
  x + y + z

partial (add3) (1, 2, 3)   // 6

partial (add3, 1) (2, 3)   // 6

partial (add3, 1, 2) (3)   // 6

partial (add3, 1, 2, 3) () // 6

partial (add3, 1, 1, 1, 1) (1, 1, 1, 1, 1) // 3

Đây là bản demo hoạt động partialmà bạn có thể chơi bằng trình duyệt của riêng mình -

const partial = (f, ...a) => (...b) =>
  f (...a, ...b)
  
const preventDefault = (f, event) =>
  ( event .preventDefault ()
  , f (event)
  )
  
const logKeypress = event =>
  console .log (event.which)
  
document
  .querySelector ('input[name=foo]')
  .addEventListener ('keydown', partial (preventDefault, logKeypress))
<input name="foo" placeholder="type here to see ascii codes" size="50">

63
sdgluck 2015-09-26 04:05.

Việc hiểu các cú pháp có sẵn của các hàm mũi tên sẽ giúp bạn hiểu được hành vi mà chúng đang giới thiệu khi được 'xâu chuỗi' như trong các ví dụ bạn đã cung cấp.

Khi một hàm mũi tên được viết mà không có dấu ngoặc nhọn, có hoặc không có nhiều tham số, thì biểu thức cấu thành phần thân của hàm được trả về một cách ngầm định . Trong ví dụ của bạn, biểu thức đó là một hàm mũi tên khác.

No arrow funcs              Implicitly return `e=>{…}`    Explicitly return `e=>{…}` 
---------------------------------------------------------------------------------
function (field) {         |  field => e => {            |  field => {
  return function (e) {    |                             |    return e => {
      e.preventDefault()   |    e.preventDefault()       |      e.preventDefault()
  }                        |                             |    }
}                          |  }                          |  }

Một ưu điểm khác của việc viết các hàm ẩn danh bằng cú pháp mũi tên là chúng được liên kết từ vựng với phạm vi mà chúng được xác định. Từ 'Hàm mũi tên' trên MDN :

Một biểu hiện mũi tên chức năng 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 này giá trị. Hàm mũi tên luôn ẩn danh .

Điều này đặc biệt thích hợp trong ví dụ của bạn vì nó được lấy từ một ứng dụng reactjs . Như đã chỉ ra bởi @naomik, trong React, bạn thường truy cập các hàm thành viên của một thành phần bằng cách sử dụng this. Ví dụ:

Unbound                     Explicitly bound            Implicitly bound 
------------------------------------------------------------------------------
function (field) {         |  function (field) {       |  field => e => {
  return function (e) {    |    return function (e) {  |    
      this.setState(...)   |      this.setState(...)   |    this.setState(...)
  }                        |    }.bind(this)           |    
}                          |  }.bind(this)             |  }
57
Rahil Ahmad 2018-01-02 18:47.

Một mẹo chung, nếu bạn bối rối bởi bất kỳ cú pháp JS mới nào và cách nó sẽ biên dịch, bạn có thể kiểm tra babel . Ví dụ, sao chép mã của bạn trong babel và chọn cài đặt trước es2015 sẽ cho kết quả như thế này

handleChange = function handleChange(field) {
 return function (e) {
 e.preventDefault();
  // Do something here
   };
 };

47
LifeQuery 2015-09-26 04:02.

Hãy nghĩ về nó như thế này, mỗi khi bạn nhìn thấy một mũi tên, bạn thay thế nó bằng function.
function parametersđược xác định trước mũi tên.
Vì vậy, trong ví dụ của bạn:

field => // function(field){}
e => { e.preventDefault(); } // function(e){e.preventDefault();}

và sau đó cùng nhau:

function (field) { 
    return function (e) { 
        e.preventDefault(); 
    };
}

Từ các tài liệu :

// Basic syntax:
(param1, param2, paramN) => { statements }
(param1, param2, paramN) => expression
   // equivalent to:  => { return expression; }

// Parentheses are optional when there's only one argument:
singleParam => { statements }
singleParam => expression
37
sultan 2019-02-08 06:34.

Ngắn gọn và đơn giản 🎈

Nó là một hàm trả về một hàm khác được viết theo cách ngắn gọn.

const handleChange = field => e => {
  e.preventDefault()
  // Do something here
}

// is equal to 
function handleChange(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
  }
}

Tại sao mọi người làm điều đó

Bạn đã gặp phải khi nào bạn cần viết một hàm có thể được tùy chỉnh? Hoặc bạn phải viết một hàm gọi lại có các tham số (đối số) cố định, nhưng bạn cần truyền thêm biến cho hàm nhưng tránh các biến toàn cục? Nếu câu trả lời của bạn là " " thì đó là cách để làm điều đó.

Ví dụ, chúng tôi có một buttoncuộc gọi lại với onClick. Và chúng ta cần truyền idđến hàm, nhưng onClickchỉ chấp nhận một tham số event, chúng ta không thể truyền thêm các tham số bên trong như thế này:

const handleClick = (event, id) {
  event.preventDefault()
  // Dispatch some delete action by passing record id
}

Nó sẽ không làm việc!

Do đó, chúng ta tạo một hàm sẽ trả về một hàm khác với phạm vi biến của riêng nó mà không có bất kỳ biến toàn cục nào, vì các biến toàn cục là ác 😈.

Bên dưới hàm handleClick(props.id)}sẽ được gọi và trả về một hàm và nó sẽ có idtrong phạm vi của nó! Bất kể nó được nhấn bao nhiêu lần, các id sẽ không ảnh hưởng hoặc thay đổi lẫn nhau, chúng hoàn toàn bị cô lập.

const handleClick = id => event {
  event.preventDefault()
  // Dispatch some delete action by passing record id
}

const Confirm = props => (
  <div>
    <h1>Are you sure to delete?</h1>
    <button onClick={handleClick(props.id)}>
      Delete
    </button>
  </div
)

3
Don Kartacs 2019-11-16 04:31.

Nó có thể không hoàn toàn liên quan, nhưng vì câu hỏi đã đề cập đến trường hợp sử dụng phản ứng (và tôi tiếp tục gặp phải chủ đề SO này): Có một khía cạnh quan trọng của hàm mũi tên kép không được đề cập rõ ràng ở đây. Chỉ có mũi tên 'đầu tiên' (hàm) được đặt tên (và do đó 'có thể phân biệt được' theo thời gian chạy), bất kỳ mũi tên nào sau đây đều ẩn danh và theo quan điểm của React được coi là đối tượng 'mới' trên mỗi lần hiển thị.

Vì vậy, chức năng mũi tên kép sẽ khiến bất kỳ PureComponent nào luôn hiển thị.

Thí dụ

Bạn có một thành phần chính với một trình xử lý thay đổi là:

handleChange = task => event => { ... operations which uses both task and event... };

và với một kết xuất như:

{ tasks.map(task => <MyTask handleChange={this.handleChange(task)}/> }

Sau đó, handleChange được sử dụng trên một đầu vào hoặc nhấp chuột. Và tất cả điều này đều hoạt động và trông rất đẹp. NHƯNG nó có nghĩa là bất kỳ thay đổi nào khiến cha mẹ kết xuất (như thay đổi trạng thái hoàn toàn không liên quan) cũng sẽ hiển thị lại TẤT CẢ MyTask của bạn mặc dù chúng là PureComponents.

Điều này có thể được giảm bớt bằng nhiều cách như chuyển mũi tên 'ngoài cùng' và đối tượng mà bạn cung cấp cho nó hoặc viết một hàm shouldUpdate tùy chỉnh hoặc quay lại những điều cơ bản như viết các hàm có tên (và liên kết các hàm này theo cách thủ công ...)

1
Shubham Khatri 2019-02-07 20:08.

Ví dụ trong câu hỏi của bạn là một ví dụ curried functionsử dụng arrow functionvà có một implicit returncho đối số đầu tiên.

Hàm mũi tên ràng buộc từ vựng điều này tức là chúng không có thisđối số của riêng mình mà lấy thisgiá trị từ phạm vi bao quanh

Tương đương với mã trên sẽ là

const handleChange = (field) {
  return function(e) {
     e.preventDefault();
     /// Do something here
  }.bind(this);
}.bind(this);

Một điều nữa cần lưu ý về ví dụ của bạn là định nghĩa handleChangenhư một const hoặc một hàm. Có thể bạn đang sử dụng nó như một phần của phương thức lớp và nó sử dụngclass fields syntax

vì vậy thay vì liên kết trực tiếp hàm bên ngoài, bạn sẽ liên kết nó trong hàm tạo lớp

class Something{
    constructor(props) {
       super(props);
       this.handleChange = this.handleChange.bind(this);
    }
    handleChange(field) {
        return function(e) {
           e.preventDefault();
           // do something
        }
    }
}

Một điều khác cần lưu ý trong ví dụ là sự khác biệt giữa trả về ngầm định và rõ ràng.

const abc = (field) => field * 2;

Trên đây là một ví dụ về trả lại ngầm định tức là. nó nhận trường giá trị làm đối số và trả về kết quả field*2chỉ định rõ ràng hàm để trả về

Đối với một trả về rõ ràng, bạn sẽ yêu cầu phương thức trả về giá trị một cách rõ ràng

const abc = () => { return field*2; }

Một điều khác cần lưu ý về các hàm arrow là chúng không có hàm riêng argumentsmà thừa hưởng từ phạm vi cha mẹ.

Ví dụ: nếu bạn chỉ định nghĩa một hàm mũi tên như

const handleChange = () => {
   console.log(arguments) // would give an error on running since arguments in undefined
}

Như một hàm mũi tên thay thế cung cấp các tham số còn lại mà bạn có thể sử dụng

const handleChange = (...args) => {
   console.log(args);
}

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Một thương hiệu kế thừa khác có được cuộc sống mới khi những người chủ mới của Black Opal có được Hội chợ thời trang

Một thương hiệu kế thừa khác có được cuộc sống mới khi những người chủ mới của Black Opal có được Hội chợ thời trang

Desiree Rogers, trái, và Cheryl Mayberry McKissack Chuyển sang, Fenty Beauty và Pat McGrath, có một đế chế làm đẹp mới do phụ nữ làm chủ đang trỗi dậy. Sau thương vụ mua lại mỹ phẩm Black Opal vào tháng 9, đội ngũ quyền lực của Giám đốc điều hành công ty Desiree Rogers và Chủ tịch Cheryl Mayberry McKissack đã thông báo mua lại thương hiệu làm đẹp tiên phong Fashion Fair từ người sáng lập Johnson Publishing Company (JPC).

Ngoài việc trở nên vô nghĩa, các bên bộc lộ giới tính giờ đây đã trở nên chết người

Ngoài việc trở nên vô nghĩa, các bên bộc lộ giới tính giờ đây đã trở nên chết người

Đối với những người có quá nhiều thời gian, tiệc tiết lộ giới tính là một cách thú vị để không cần áp đặt những định kiến ​​hạn chế lên thai nhi trước một đối tượng bạn bè giả vờ quan tâm một cách lịch sự. Tuy nhiên, việc chỉ dựa vào những chiếc bánh nướng có màu nhân tạo để biểu thị một tiếng hoo-ha hoặc một đứa trẻ đi tè đã trở nên xa xỉ trong các bậc cha mẹ trên Instagram.

Kirstjen Nielsen đang cố gắng đổi mới bản thân với tư cách là một người phụ nữ 'nói ra sự thật cho sức mạnh'

Kirstjen Nielsen đang cố gắng đổi mới bản thân với tư cách là một người phụ nữ 'nói ra sự thật cho sức mạnh'

Hôm thứ Tư, cựu Bộ trưởng An ninh Nội địa Kirstjen Nielsen vì một lý do nào đó đã được đưa ra một diễn đàn để phát biểu tại Hội nghị thượng đỉnh Những người phụ nữ quyền lực nhất của Fortune. Và có thể đoán trước được, người phụ nữ giám sát các nỗ lực (đang diễn ra) của chính quyền Trump nhằm chia cắt các gia đình ở biên giới đã sử dụng thời gian của mình như một cơ hội để tự bảo vệ mình và tự nhận mình là người — và hãy hít thở sâu ở đây — “đã nói sự thật với quyền lực.

Toyota Racing Development sẽ cho ra mắt Supra 3000GT Concept, Massive Wing vào tháng tới

Toyota Racing Development sẽ cho ra mắt Supra 3000GT Concept, Massive Wing vào tháng tới

Vì thế hệ mới nhất của chiếc xe điều chỉnh được yêu thích trên thế giới hiện đã có mặt tại đây, nên chỉ có điều kiện là Toyota Racing Development sẽ đưa phiên bản Supra thế hệ thứ năm sửa đổi của riêng mình đến SEMA vào tháng tới. Toyota đã cho chúng tôi một gợi ý về những gì sẽ xảy ra trong tuần này: một chiếc Concept GR Supra 3000GT hiện đại.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language