JavaScript có tốt cho lập trình chức năng không?

Quên bất cứ điều gì bạn nghĩ rằng bạn biết về JavaScript và tiếp cận tài liệu này với tư duy của người mới bắt đầu. Để giúp bạn làm điều đó, chúng tôi sẽ xem xét các kiến ​​thức cơ bản về JavaScript từ đầu, như thể bạn chưa từng thấy JavaScript trước đây. Nếu bạn là người mới bắt đầu, bạn thật may mắn. Cuối cùng, một cái gì đó khám phá ES6 và lập trình chức năng từ đầu. Hy vọng rằng tất cả các khái niệm mới đều được giải thích trong quá trình thực hiện — nhưng đừng tin tưởng vào quá nhiều sự nuông chiều

Nếu bạn là một nhà phát triển dày dạn kinh nghiệm đã quen thuộc với JavaScript hoặc ngôn ngữ chức năng thuần túy, có thể bạn đang nghĩ rằng JavaScript là một lựa chọn thú vị để khám phá lập trình chức năng. Đặt những suy nghĩ đó sang một bên và cố gắng tiếp cận tài liệu với một tinh thần cởi mở. Bạn có thể thấy rằng có một cấp độ khác đối với lập trình JavaScript. Một người bạn không bao giờ biết tồn tại

Vì văn bản này có tên là “Phần mềm soạn thảo” và lập trình chức năng là cách rõ ràng để soạn thảo phần mềm (sử dụng chức năng tổng hợp hàm, hàm bậc cao hơn, v.v.), bạn có thể thắc mắc tại sao tôi không nói về Haskell, ClojureScript hoặc Elm

JavaScript có các tính năng quan trọng nhất cần thiết cho lập trình chức năng

  1. Chức năng hạng nhất. Khả năng sử dụng các hàm làm giá trị dữ liệu. chuyển các hàm làm đối số, trả về hàm và gán hàm cho các biến và thuộc tính đối tượng. Thuộc tính này cho phép các chức năng bậc cao hơn, cho phép ứng dụng một phần, pha cà ri và thành phần
  2. Hàm ẩn danh và cú pháp lambda ngắn gọn. x => x * 2 là một biểu thức hàm hợp lệ trong JavaScript. Lambda ngắn gọn giúp làm việc với các hàm bậc cao dễ dàng hơn
  3. đóng cửa. Một bao đóng là một gói của một chức năng với môi trường từ vựng của nó. Các bao đóng được tạo tại thời điểm tạo chức năng. Khi một chức năng được xác định bên trong một chức năng khác, nó có quyền truy cập vào các liên kết biến trong chức năng bên ngoài, ngay cả sau khi chức năng bên ngoài thoát. Các bao đóng là cách các ứng dụng một phần nhận được các đối số cố định của chúng. Đối số cố định là đối số bị ràng buộc trong phạm vi đóng của hàm được trả về. Trong add2(1)(2), 1 là một đối số cố định trong hàm được trả về bởi add2(1)
JavaScript nào bị thiếu

JavaScript là ngôn ngữ đa mô hình, nghĩa là nó hỗ trợ lập trình theo nhiều phong cách khác nhau. Các phong cách khác được JavaScript hỗ trợ bao gồm lập trình thủ tục (bắt buộc) (như C), trong đó các hàm đại diện cho một chương trình con hướng dẫn có thể được gọi lặp lại để tái sử dụng và tổ chức, lập trình hướng đối tượng, trong đó các đối tượng — không phải hàm — là các khối xây dựng chính, . Nhược điểm của ngôn ngữ đa mô hình là lập trình hướng đối tượng và bắt buộc có xu hướng ngụ ý rằng hầu hết mọi thứ cần phải thay đổi được

Đột biến là thay đổi cấu trúc dữ liệu xảy ra tại chỗ. Ví dụ

const foo = {
bar: 'baz'
};
foo.bar = 'qux'; // mutation

Các đối tượng thường cần phải có thể thay đổi để các thuộc tính của chúng có thể được cập nhật bằng các phương thức. Trong lập trình mệnh lệnh, hầu hết các cấu trúc dữ liệu đều có thể thay đổi để cho phép thao tác tại chỗ hiệu quả đối với các đối tượng và mảng

Dưới đây là một số tính năng mà một số ngôn ngữ chức năng có, mà JavaScript không có

  1. độ tinh khiết. Trong một số ngôn ngữ FP, độ tinh khiết được thực thi bởi ngôn ngữ. Các biểu thức có tác dụng phụ không được phép
  2. tính bất biến. Một số ngôn ngữ FP vô hiệu hóa đột biến. Thay vì thay đổi cấu trúc dữ liệu hiện có, chẳng hạn như một mảng hoặc đối tượng, các biểu thức đánh giá cấu trúc dữ liệu mới. Điều này nghe có vẻ không hiệu quả, nhưng hầu hết các ngôn ngữ chức năng đều sử dụng cấu trúc dữ liệu trie dưới mui xe, có tính năng chia sẻ cấu trúc. nghĩa là đối tượng cũ và đối tượng mới chia sẻ tham chiếu đến dữ liệu giống nhau
  3. đệ quy. Đệ quy là khả năng một hàm tự tham chiếu cho mục đích lặp lại. Trong nhiều ngôn ngữ FP, đệ quy là cách duy nhất để lặp. Không có câu lệnh vòng lặp như vòng lặp for, while hoặc do

độ tinh khiết. Trong JavaScript, độ tinh khiết phải đạt được theo quy ước. Nếu bạn không xây dựng hầu hết ứng dụng của mình bằng cách soạn các hàm thuần túy, thì bạn không lập trình bằng kiểu chức năng. Thật không may, JavaScript rất dễ đi chệch hướng do vô tình tạo và sử dụng các hàm không trong sáng

tính bất biến. Trong các ngôn ngữ chức năng thuần túy, tính bất biến thường được thực thi. JavaScript thiếu các cấu trúc dữ liệu dựa trên bộ ba hiệu quả, không thay đổi được sử dụng bởi hầu hết các ngôn ngữ chức năng, nhưng có các thư viện trợ giúp, bao gồm cả Immutable. js và Mori. Tôi hy vọng rằng các phiên bản tương lai của đặc tả ECMAScript sẽ bao gồm các cấu trúc dữ liệu bất biến

Có những dấu hiệu mang lại hy vọng, chẳng hạn như việc bổ sung từ khóa const trong ES6. Không thể chỉ định lại ràng buộc tên được xác định bằng const để tham chiếu đến một giá trị khác. Điều quan trọng là phải hiểu rằng const không đại diện cho một giá trị bất biến

Không thể chỉ định lại một đối tượng const để tham chiếu đến một đối tượng hoàn toàn khác, nhưng đối tượng mà nó tham chiếu có thể bị thay đổi thuộc tính. JavaScript cũng có khả năng x => x * 22 đối tượng, nhưng những đối tượng đó chỉ bị đóng băng ở cấp gốc, nghĩa là một đối tượng lồng nhau vẫn có thể có các thuộc tính của các thuộc tính của nó bị thay đổi. Nói cách khác, vẫn còn một chặng đường dài phía trước trước khi chúng ta thấy các bất biến tổng hợp thực sự trong đặc tả JavaScript

đệ quy. Về mặt kỹ thuật, JavaScript hỗ trợ đệ quy, nhưng hầu hết các ngôn ngữ chức năng đều có một tính năng gọi là tối ưu hóa cuộc gọi đuôi. Tối ưu hóa cuộc gọi đuôi là một tính năng cho phép các hàm đệ quy sử dụng lại các khung ngăn xếp cho các cuộc gọi đệ quy

Nếu không tối ưu hóa cuộc gọi đuôi, ngăn xếp cuộc gọi có thể phát triển không giới hạn và gây tràn ngăn xếp. Về mặt kỹ thuật, JavaScript có một dạng tối ưu hóa cuộc gọi đuôi hạn chế trong đặc tả ES6. Thật không may, chỉ một trong những công cụ trình duyệt chính triển khai nó và việc tối ưu hóa đã được triển khai một phần và sau đó bị xóa khỏi Babel (trình biên dịch JavaScript tiêu chuẩn phổ biến nhất, được sử dụng để biên dịch ES6 thành ES5 để sử dụng trong các trình duyệt cũ hơn)

dòng dưới cùng. Vẫn không an toàn khi sử dụng đệ quy cho các lần lặp lớn — ngay cả khi bạn cẩn thận gọi hàm ở vị trí đuôi

JavaScript có gì mà ngôn ngữ chức năng thuần túy thiếu

Một người theo chủ nghĩa thuần túy sẽ nói với bạn rằng khả năng biến đổi của JavaScript là nhược điểm chính của nó, điều đó đúng. Tuy nhiên, tác dụng phụ và đột biến đôi khi có lợi. Trên thực tế, không thể tạo ra các ứng dụng hiện đại hữu ích nhất mà không có tác dụng phụ. Các ngôn ngữ chức năng thuần túy như Haskell sử dụng các tác dụng phụ, nhưng ngụy trang chúng khỏi các hàm thuần túy bằng cách sử dụng các hộp được gọi là đơn nguyên, cho phép chương trình duy trì trạng thái thuần túy mặc dù các tác dụng phụ do các đơn nguyên đại diện là không thuần túy

Rắc rối với các đơn nguyên là, mặc dù việc sử dụng chúng khá đơn giản, nhưng việc giải thích đơn nguyên là gì đối với một người không quen thuộc với nhiều ví dụ cũng giống như giải thích màu “xanh lam” trông như thế nào đối với một người mù.

“Một đơn nguyên là một monoid trong danh mục endofunctor, vấn đề là gì?” . “Lịch sử ngôn ngữ lập trình ngắn gọn, không đầy đủ và hầu hết là sai lầm”

Thông thường, tác phẩm nhại phóng đại mọi thứ để làm cho điểm hài hước trở nên hài hước hơn. Trong trích dẫn trên, lời giải thích về các đơn nguyên thực sự được đơn giản hóa từ trích dẫn ban đầu, như sau

“Một đơn nguyên trong x => x * 23 chỉ là một monoid trong danh mục endofunctor của x => x * 23, với sản phẩm x => x * 25 được thay thế bằng thành phần của endofunctor và đơn vị do endofunctor nhận dạng đặt. " ~ Đường Saunders Mac. "Hạng mục dành cho nhà toán học đang làm việc"

Mặc dù vậy, theo tôi, sợ hãi các đơn nguyên là lý luận yếu. Cách tốt nhất để tìm hiểu các đơn nguyên không phải là đọc một đống sách và bài đăng trên blog về chủ đề này, mà là nhảy vào và bắt đầu sử dụng chúng. Như với hầu hết mọi thứ trong lập trình chức năng, từ vựng học thuật không thể hiểu được khó hiểu hơn nhiều so với các khái niệm. Tin tôi đi, bạn không cần phải hiểu Saunders Mac Lane để hiểu lập trình chức năng

Mặc dù nó có thể không hoàn toàn lý tưởng cho mọi phong cách lập trình, nhưng rõ ràng JavaScript là một ngôn ngữ có mục đích chung được thiết kế để nhiều người có thể sử dụng được với nhiều phong cách và nền tảng lập trình khác nhau.

Theo Brendan Eich, điều này đã được cố ý ngay từ đầu. Netscape phải hỗ trợ hai loại lập trình viên

“…các tác giả thành phần, những người đã viết bằng C++ hoặc (chúng tôi hy vọng) Java; . ”

Ban đầu, ý định là Netscape sẽ hỗ trợ hai ngôn ngữ khác nhau và ngôn ngữ kịch bản có thể giống với Scheme (một phương ngữ của Lisp). Một lần nữa, Brendan Eich

“Tôi được tuyển dụng vào Netscape với lời hứa ‘làm Scheme’ trên trình duyệt. ”

JavaScript phải là một ngôn ngữ mới

“Diktat từ quản lý kỹ thuật cấp cao là ngôn ngữ phải 'trông giống Java'. Điều đó đã loại trừ Perl, Python và Tcl, cùng với Scheme. ”

Vì vậy, những ý tưởng trong đầu Brendan Eich ngay từ đầu là

  1. Sơ đồ trong trình duyệt
  2. Trông giống như Java

Nó thậm chí còn giống như một mớ hỗn độn hơn

“Tôi không tự hào, nhưng tôi rất vui vì tôi đã chọn các chức năng hạng nhất của Scheme-ish và các nguyên mẫu Self-ish (mặc dù là số ít) làm thành phần chính. Các ảnh hưởng của Java, đặc biệt là các lỗi Ngày y2k nhưng cũng là nguyên thủy so với. phân biệt đối tượng (e. g. , chuỗi so với. String), thật không may. ”

Tôi muốn thêm vào danh sách các tính năng giống như Java “đáng tiếc” cuối cùng đã được đưa vào JavaScript

  • Các hàm xây dựng và từ khóa x => x * 26, với cách gọi và ngữ nghĩa sử dụng khác với các hàm của nhà sản xuất
  • Một từ khóa x => x * 27 với tổ tiên đơn x => x * 28 làm cơ chế kế thừa chính
  • Người dùng có xu hướng nghĩ về một x => x * 27 như thể đó là một loại tĩnh (không phải vậy)

Lời khuyên của tôi. Tránh những thứ đó bất cứ khi nào bạn có thể

Chúng tôi thật may mắn khi cuối cùng JavaScript lại trở thành một ngôn ngữ có khả năng như vậy, bởi vì hóa ra cách tiếp cận theo kịch bản đã chiến thắng cách tiếp cận “thành phần” (ngày nay, các tiện ích mở rộng Java, Flash và ActiveX không được hỗ trợ trong một số lượng lớn trình duyệt đã cài đặt)

Cuối cùng chúng tôi đã đạt được một ngôn ngữ được trình duyệt hỗ trợ trực tiếp. JavaScript

Điều đó có nghĩa là các trình duyệt ít cồng kềnh hơn và ít lỗi hơn, vì chúng chỉ cần hỗ trợ một bộ ràng buộc ngôn ngữ duy nhất. JavaScript. Bạn có thể nghĩ rằng WebAssugging là một ngoại lệ, nhưng một trong những mục tiêu thiết kế của WebAssugging là chia sẻ các ràng buộc ngôn ngữ của JavaScript bằng cách sử dụng Cây cú pháp trừu tượng tương thích (AST). Trên thực tế, các bản trình diễn đầu tiên đã biên dịch WebAssugging thành một tập hợp con của JavaScript được gọi là ASM. js

Vị trí là ngôn ngữ lập trình mục đích chung tiêu chuẩn duy nhất cho nền tảng web cho phép JavaScript vượt qua làn sóng phổ biến ngôn ngữ lớn nhất trong lịch sử phần mềm

Ứng dụng ăn mòn thế giới, web ăn mòn ứng dụng và JavaScript ăn mòn web

Bằng nhiều biện pháp, JavaScript hiện là ngôn ngữ lập trình phổ biến nhất trên thế giới

JavaScript không phải là công cụ lý tưởng để lập trình chức năng, nhưng nó là một công cụ tuyệt vời để xây dựng các ứng dụng lớn trên các nhóm phân tán, rất lớn, nơi các nhóm khác nhau có thể có những ý tưởng khác nhau về cách xây dựng ứng dụng

Một số nhóm có thể tập trung vào việc viết kịch bản, nơi lập trình mệnh lệnh đặc biệt hữu ích. Những người khác có thể tập trung vào việc xây dựng các khái niệm trừu tượng về kiến ​​trúc, trong đó một chút suy nghĩ OO (kiềm chế, cẩn thận) có thể không phải là một ý tưởng tồi. Vẫn còn những người khác có thể nắm lấy lập trình chức năng, giảm các hành động của người dùng bằng cách sử dụng các hàm thuần túy để quản lý trạng thái ứng dụng một cách xác định, có thể kiểm tra được. Các thành viên trong các nhóm này đều sử dụng cùng một ngôn ngữ, nghĩa là họ có thể dễ dàng trao đổi ý kiến, học hỏi lẫn nhau và phát triển dựa trên công việc của nhau

Trong JavaScript, tất cả những ý tưởng này có thể cùng tồn tại, điều này cho phép nhiều người nắm bắt JavaScript hơn, điều này đã dẫn đến sổ đăng ký gói nguồn mở lớn nhất trên thế giới (kể từ tháng 2 năm 2017), npm

Sức mạnh thực sự của JavaScript là sự đa dạng về suy nghĩ và người dùng trong hệ sinh thái. Nó có thể không hoàn toàn là ngôn ngữ lý tưởng cho những người theo chủ nghĩa thuần túy lập trình chức năng, nhưng nó có thể là ngôn ngữ lý tưởng để làm việc cùng nhau bằng một ngôn ngữ hoạt động trên mọi nền tảng mà bạn có thể tưởng tượng — quen thuộc với những người đến từ các ngôn ngữ phổ biến khác như Java, Lisp . JavaScript sẽ không cảm thấy thoải mái một cách lý tưởng đối với người dùng có bất kỳ nền tảng nào trong số đó, nhưng họ có thể cảm thấy đủ thoải mái để học ngôn ngữ và nhanh chóng làm việc hiệu quả

Tôi đồng ý rằng JavaScript không phải là ngôn ngữ tốt nhất cho các lập trình viên chức năng. Tuy nhiên, không có ngôn ngữ chức năng nào khác có thể khẳng định rằng đó là ngôn ngữ mà mọi người có thể sử dụng và chấp nhận, và như ES6 đã chứng minh. JavaScript có thể và sẽ phục vụ tốt hơn nhu cầu của người dùng quan tâm đến lập trình chức năng. Thay vì từ bỏ JavaScript và hệ sinh thái đáng kinh ngạc của nó được hầu hết mọi công ty trên thế giới sử dụng, tại sao không nắm lấy nó và dần dần biến nó thành ngôn ngữ tốt hơn cho thành phần phần mềm?

Hiện tại, JavaScript đã là một ngôn ngữ lập trình chức năng đủ tốt, nghĩa là mọi người đang xây dựng tất cả các loại thứ hữu ích và thú vị trong JavaScript, sử dụng các kỹ thuật lập trình chức năng. Netflix (và mọi ứng dụng được xây dựng bằng Angular 2+) sử dụng các tiện ích chức năng dựa trên RxJS. Facebook sử dụng các khái niệm về hàm thuần túy, hàm bậc cao hơn và các thành phần bậc cao hơn trong React để xây dựng Facebook và Instagram. PayPal, KhanAcademy và Flipkart sử dụng Redux để quản lý trạng thái

Họ không đơn độc. Angular, React, Redux và Lodash là những khung và thư viện hàng đầu trong hệ sinh thái ứng dụng JavaScript và tất cả chúng đều chịu ảnh hưởng nặng nề của lập trình chức năng — hoặc trong trường hợp của Lodash và Redux, được xây dựng với mục đích rõ ràng là kích hoạt các mẫu lập trình chức năng

“Tại sao lại là JavaScript?” . Dù yêu hay ghét nó, JavaScript đã đánh cắp danh hiệu “ngôn ngữ lập trình chức năng phổ biến nhất” từ Lisp, vốn là ngôn ngữ mang tiêu chuẩn trong nhiều thập kỷ. Đúng vậy, Haskell là một trình mang tiêu chuẩn phù hợp hơn nhiều cho các khái niệm lập trình chức năng ngày nay, nhưng mọi người không xây dựng nhiều ứng dụng thực trong Haskell

Tại bất kỳ thời điểm nào, có gần một trăm nghìn cơ hội việc làm JavaScript tại Hoa Kỳ và hàng trăm nghìn cơ hội việc làm khác trên toàn thế giới. Học Haskell sẽ dạy bạn rất nhiều về lập trình chức năng, nhưng học JavaScript sẽ dạy bạn rất nhiều về cách xây dựng các ứng dụng sản xuất cho công việc thực tế

Ứng dụng ăn mòn thế giới, web ăn mòn ứng dụng và JavaScript ăn mòn web

Mua sách. Mục lục. < Trước. Tiếp theo >

Tìm hiểu thêm tại EricElliottJS. com

Các bài học video với các thử thách mã tương tác có sẵn cho các thành viên của EricElliottJS. com. Nếu bạn chưa phải là thành viên, hãy đăng ký ngay hôm nay

Eric Elliott là cố vấn nền tảng và sản phẩm công nghệ, tác giả của “Phần mềm soạn thảo”, đồng sáng lập của EricElliottJS. com và DevAnywhere. io và cố vấn nhóm phát triển. Anh ấy đã đóng góp vào trải nghiệm phần mềm cho Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC và các nghệ sĩ thu âm hàng đầu bao gồm Usher, Frank Ocean, Metallica, v.v.

Ngôn ngữ nào là tốt nhất cho lập trình chức năng?

Danh sách ngôn ngữ lập trình hàm tốt nhất .
áo choàng
tiên dược
Haskell
Scala
con trăn
đàn nhị

JS có chức năng hay OOP không?

Không có lớp cố hữu nào trong JavaScript. Thay vào đó, các đối tượng kế thừa trực tiếp từ các đối tượng khác thông qua thuộc tính nguyên mẫu. Nếu bạn muốn tìm hiểu thêm về cách thức hoạt động của tính năng này, tôi đã tạo hướng dẫn dành cho người mới bắt đầu về các lớp JavaScript. JavaScript hỗ trợ các phong cách lập trình hướng đối tượng, mệnh lệnh và chức năng .

Tại sao lập trình hàm lại quan trọng trong JavaScript?

Ưu điểm của lập trình hàm . Nó cho phép chúng tôi triển khai phép tính lambda trong chương trình của mình để giải các bài toán phức tạp. Một số ngôn ngữ lập trình hỗ trợ các hàm lồng nhau giúp cải thiện khả năng bảo trì của mã. Nó làm giảm các vấn đề phức tạp thành các phần đơn giản. It improves modularity. It allows us to implement lambda calculus in our program to solve complex problems. Some programming languages support nested functions which improve maintainability of the code. It reduces complex problems into simple pieces.