Hướng dẫn is javascript a functional language - javascript có phải là ngôn ngữ chức năng không

Đầu tiên, chúng ta phải xác định lập trình chức năng. Tôi định nghĩa nó là bất kỳ ngôn ngữ nào hỗ trợ và đặc quyền cho phong cách lập trình được chia sẻ bởi các ngôn ngữ chức năng [hoặc ít nhất là được thỏa thuận rộng rãi] như sơ đồ, vợt, haskell hoặc clojure.natively supports and privileges the style of programming shared by canonical [or at least widely agreed-upon] functional languages like Scheme, Racket, Haskell or Clojure.

Các ngôn ngữ khác, như OCAML, Elixir và Scala có sự hỗ trợ chức năng sâu hơn nhiều so với JS, nhưng vẫn có xu hướng được coi là đa hướng. Chức năng là một phổ.

Tất cả những điều này rất cởi mở với cuộc tranh luận và nitpicking vô tận, nhưng định nghĩa này có vẻ đủ vững chắc để đưa ra trường hợp rằng JS không phải là ngôn ngữ chức năng nghiêm túc và có lẽ sẽ không bao giờ là một ngôn ngữ khác nhau Chức năng hạng nhất.

Hãy chọn một tính năng cụ thể. Ngôn ngữ nên thực hiện tối ưu hóa cuộc gọi đuôi để bạn có thể viết các hàm đệ quy trên các cấu trúc dữ liệu tuyến tính. Hầu như tất cả các triển khai chính của JS đều không cung cấp tính năng fudamental này mà chúng tôi mong đợi từ một ngôn ngữ "chức năng" điển hình [theo định nghĩa trên] và không có kế hoạch tại thời điểm viết [xem các chức năng trong cuộc gọi đuôi JavaScript được tối ưu hóa ? để biết chi tiết].

Chúng ta hãy mang lại lợi ích cho sự nghi ngờ và ném vào TCO và vẫn còn, JS không đưa ra một chút gợi ý nào về mục tiêu thiết kế bất biến mà bạn mong đợi về một ngôn ngữ chức năng "thực sự". Chỉ cần nhận

for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
1 trong ngôn ngữ mất nhiều thập kỷ và tất cả các đối tượng đều có thể thay đổi theo mặc định.

Những vấn đề này thực sự không thể được giải quyết hoàn toàn do khả năng tương thích ngược; Không thực sự có thể biến một ngôn ngữ đa mô hình thành lập thành một ngôn ngữ thực sự chức năng sau thực tế.

JS là về chức năng như, nói, Python, Perl, PHP hoặc Ruby, tất cả đều cung cấp ____ 22/________ 23/________ 24 Hoạt động trên danh sách và hỗ trợ các chức năng hoặc quy trình hạng nhất. Sự tồn tại của các hàm hạng nhất cung cấp đủ mở để ghi mã theo kiểu lập trình chức năng. Toss in Trampolines và Ramda.js và nó có vẻ thuyết phục trong nháy mắt.

Câu hỏi đặt ra là liệu các hàm hạng nhất có đủ để làm cho ngôn ngữ "chức năng" hay không. Trên thực tế, Wikipedia liệt kê tất cả các ngôn ngữ chức năng đã nói ở trên, nhưng sau đó, danh sách đó bao gồm mọi ngôn ngữ phổ biến, hiện đại, đa năng khác với C và GO [bao gồm ít nhất một ngôn ngữ xác định rõ ràng là không có chức năng theo thiết kế] vì vậy Tôi không thấy rằng định nghĩa này cung cấp nhiều giá trị phân biệt.

JavaScript là ngôn ngữ đa mô hình và có thể được viết theo các mô hình lập trình khác nhau. Một mô hình lập trình về cơ bản là một loạt các quy tắc mà bạn tuân theo khi viết mã.

Những mô hình này tồn tại vì chúng giải quyết các vấn đề mà các lập trình viên phải đối mặt và họ có các quy tắc và hướng dẫn riêng để giúp bạn viết mã tốt hơn.

Mỗi mô hình giúp bạn giải quyết một vấn đề cụ thể. Vì vậy, thật hữu ích khi có một cái nhìn tổng quan về mỗi người trong số họ. Chúng tôi sẽ bao gồm lập trình chức năng ở đây.

Vào cuối bài viết này, có một số tài nguyên bạn có thể sử dụng để đi xa hơn nếu bạn thích phần giới thiệu này.

Ngoài ra còn có một thuật ngữ GitHub sẽ giúp bạn giải mã một số biệt ngữ mà lập trình chức năng sử dụng.

Cuối cùng, bạn sẽ tìm thấy một nơi để có được mã hóa bẩn với các ví dụ thực tế và một repo github đầy đủ các tài nguyên bạn có thể sử dụng để tìm hiểu thêm. Vì vậy, chúng ta hãy đi sâu vào.

Các mô hình lập trình bắt buộc vs bắt buộc

Một ví dụ về những mô hình mà tôi đã nói đến lúc đầu là lập trình hướng đối tượng. Một cái khác là lập trình chức năng.

Vậy chính xác thì lập trình chức năng là gì?

Lập trình chức năng là một mô hình phụ của mô hình lập trình khai báo, với các quy tắc riêng để tuân theo khi viết mã.Declarative programming paradigm, with its own rules to follow when writing code.

Mô hình lập trình khai báo là gì?

Nếu bạn mã hóa bằng một ngôn ngữ tuân theo mô hình khai báo, bạn viết mã chỉ định những gì bạn muốn làm, mà không cần nói làm thế nào.what you want to do, without saying how.

Một ví dụ siêu đơn giản về điều này là SQL hoặc HTML:

SELECT * FROM customers

Trong các ví dụ mã trên, bạn không thực hiện

for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
5 hoặc làm thế nào để hiển thị
for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
6. Bạn chỉ nói với máy tính phải làm gì, mà không cần làm thế nào.

Từ mô hình này, có những cuộc tranh nhau như lập trình chức năng. Thêm về điều đó dưới đây.Functional programming. More on that below.

Mô hình lập trình bắt buộc là gì?

Nếu bạn đang mã hóa bằng một ngôn ngữ theo mô hình bắt buộc/thủ tục, bạn viết mã cho biết cách làm điều gì đó.how to do something.

Ví dụ: nếu bạn làm điều gì đó như dưới đây:

for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}

Bạn đang nói với máy tính chính xác phải làm gì. Lặp lại thông qua mảng được gọi là

for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
7, và sau đó
for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
8 mỗi mục trong mảng.

Tuyên bố vs lập trình bắt buộc

Bạn có thể viết JavaScript trong mô hình khai báo hoặc mô hình bắt buộc. Đây là ý nghĩa của mọi người khi họ nói đó là ngôn ngữ đa Paradigm. Đó chỉ là mã chức năng theo mô hình khai báo.Declarative paradigm or the Imperative paradigm. This is what people mean when they say it's a multi-paradigm language. It's just that functional code follows the Declarative paradigm.

Nếu nó giúp bạn nhớ, một ví dụ về lệnh khai báo sẽ là yêu cầu máy tính làm cho bạn một tách trà [tôi không quan tâm bạn làm thế nào, chỉ cần mang cho tôi một ít trà].

Trong khi bất khả xâm phạm, bạn sẽ phải nói:

  • Đi vào bếp.
  • Nếu có ấm trong phòng, và nó có đủ nước cho một tách trà, hãy bật ấm.
  • Nếu có một ấm đun nước trong phòng, và nó không có đủ nước cho một tách trà, hãy đổ đầy ấm bằng nước cho một tách trà, sau đó bật ấm.
  • Và như thế

Vậy lập trình chức năng là gì?

Vậy điều này có ý nghĩa gì đối với mã chức năng?

Bởi vì đó là một mô hình phụ từ mô hình khai báo, điều này ảnh hưởng đến cách bạn viết mã chức năng. Nó thường dẫn đến ít mã hơn, bởi vì JavaScript đã có rất nhiều chức năng được xây dựng mà bạn thường cần. Đây là một lý do khiến mọi người thích mã chức năng.Declarative paradigm, this affects the way you write functional code. It generally leads to less code, because JavaScript already has a lot of the in-built functions you commonly need. This is one reason people like functional code.

Nó cũng cho phép bạn trừu tượng hóa rất nhiều [bạn không cần phải hiểu sâu về cách thức một cái gì đó được thực hiện], bạn chỉ cần gọi một chức năng làm điều đó cho bạn.

Và các quy tắc dẫn đến mã chức năng là gì?

Lập trình chức năng có thể được giải thích đơn giản bằng cách tuân theo 2 luật trong mã của bạn:

  1. Bạn kiến ​​trúc sư phần mềm của bạn từ các chức năng tinh khiết, bị cô lập
  2. Bạn tránh bị đột biến và tác dụng phụ

Hãy đào sâu vào đó.

1. Kiến trúc sư phần mềm của bạn từ các chức năng tinh khiết, bị cô lập

Hãy cùng bắt đầu lại từ đầu,

Mã chức năng sử dụng rất nhiều điều:

Chức năng thuần túy

Đầu vào tương tự luôn cung cấp cùng một đầu ra [idempotence] và không có tác dụng phụ.idempotence], and has no side effects.

Một hàm idempotent, là một hàm, khi bạn đăng ký lại kết quả cho chức năng đó một lần nữa, không tạo ra kết quả khác.idempotent function, is one that, when you reapply the results to that function again, doesn't produce a different result.

/// Example of some Math.abs uses
Math.abs['-1'];     // 1
Math.abs[-1];       // 1
Math.abs[null];     // 0


Math.abs[Math.abs[Math.abs['-1']]];           // Still returns 1
Math.abs[Math.abs[Math.abs[Math.abs['-1']]]]; // Still returns 1
an ví dụ về hàm idempotent.

Tác dụng phụ là khi mã của bạn tương tác với [đọc hoặc ghi vào] trạng thái đột biến bên ngoài.

Trạng thái đột biến bên ngoài theo nghĩa đen là bất cứ điều gì bên ngoài chức năng sẽ thay đổi dữ liệu trong chương trình của bạn. Đặt một chức năng? Đặt boolean trên một đối tượng? Xóa thuộc tính trên một đối tượng? Tất cả các thay đổi để trạng thái bên ngoài chức năng của bạn.

function setAvailability[]{
	available = true;
}
An ví dụ về trạng thái đột biến được đặt bên trong các chức năng của bạn.

Các chức năng bị cô lập

Không có sự phụ thuộc vào trạng thái của chương trình, bao gồm các biến toàn cầu có thể thay đổi.

Chúng tôi sẽ thảo luận thêm về điều này, nhưng bất cứ điều gì bạn cần phải được chuyển vào chức năng như một đối số. Điều này làm cho sự phụ thuộc của bạn [những điều mà chức năng cần phải thực hiện công việc của nó] rõ ràng hơn nhiều để xem, và dễ khám phá hơn.

Ok, vậy tại sao bạn làm mọi thứ theo cách này?

Tôi biết điều này có vẻ như rất nhiều hạn chế khiến mã của bạn khó khăn không cần thiết. Nhưng chúng không hạn chế, chúng là những hướng dẫn cố gắng ngăn bạn rơi vào các mô hình thường dẫn đến lỗi.

Khi bạn không thay đổi thực thi mã của mình, việc lấy mã của bạn với trạng thái của

for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
9 dựa trên trạng thái của ____ 30, được đặt bởi nhiều địa điểm trong mã của bạn, bạn sẽ khiến mã dễ dự đoán hơn và dễ dàng hơn về những gì đang xảy ra.

Khi bạn tuân theo mô hình chức năng, bạn sẽ thấy rằng thứ tự thực hiện mã của bạn không quan trọng như vậy.

Điều này có khá nhiều lợi ích - ví dụ, một sinh vật để sao chép một lỗi mà bạn không cần biết chính xác mỗi trạng thái của

/// Example of some Math.abs uses
Math.abs['-1'];     // 1
Math.abs[-1];       // 1
Math.abs[null];     // 0


Math.abs[Math.abs[Math.abs['-1']]];           // Still returns 1
Math.abs[Math.abs[Math.abs[Math.abs['-1']]]]; // Still returns 1
0 và ________ 32 là gì trước khi bạn chạy các chức năng của mình. Miễn là bạn có một ngăn xếp cuộc gọi [bạn biết chức năng nào đang chạy/đã chạy trước bạn], nó có thể sao chép các lỗi và giải quyết chúng dễ dàng hơn.

Khả năng tái sử dụng thông qua các chức năng bậc cao hơn

Các chức năng có thể được gán cho một biến, được chuyển vào một hàm khác hoặc được trả về từ một hàm khác giống như bất kỳ giá trị thông thường nào khác, được gọi là hàm hạng nhất.first class functions.

Trong JavaScript, tất cả các chức năng là các hàm hạng nhất. Các chức năng có trạng thái hạng nhất cho phép chúng tôi tạo các hàm bậc cao hơn.higher order functions.

Hàm thứ tự cao hơn là một hàm hoặc lấy chức năng như một đối số, trả về một hàm hoặc cả hai! Bạn có thể sử dụng các chức năng bậc cao hơn để ngừng lặp lại bản thân trong mã của mình.higher order function is a function that either take a function as an argument, returns a function, or both! You can use higher order functions to stop repeating yourself in your code.

Một cái gì đó như thế này:

// Here's a non-functional example
const ages = [12,32,32,53]
for [var i=0; i < ages.length; i++] {
    finalAge += ages[i];
}

// Here's a functional example
const ages = [12,32,32,53]
const totalAge = ages.reduce[ function[firstAge, secondAge]{
    return firstAge + secondAge;
}]

JavaScript được xây dựng

/// Example of some Math.abs uses
Math.abs['-1'];     // 1
Math.abs[-1];       // 1
Math.abs[null];     // 0


Math.abs[Math.abs[Math.abs['-1']]];           // Still returns 1
Math.abs[Math.abs[Math.abs[Math.abs['-1']]]]; // Still returns 1
3 chức năng
/// Example of some Math.abs uses
Math.abs['-1'];     // 1
Math.abs[-1];       // 1
Math.abs[null];     // 0


Math.abs[Math.abs[Math.abs['-1']]];           // Still returns 1
Math.abs[Math.abs[Math.abs[Math.abs['-1']]]]; // Still returns 1
4,
/// Example of some Math.abs uses
Math.abs['-1'];     // 1
Math.abs[-1];       // 1
Math.abs[null];     // 0


Math.abs[Math.abs[Math.abs['-1']]];           // Still returns 1
Math.abs[Math.abs[Math.abs[Math.abs['-1']]]]; // Still returns 1
5 và
/// Example of some Math.abs uses
Math.abs['-1'];     // 1
Math.abs[-1];       // 1
Math.abs[null];     // 0


Math.abs[Math.abs[Math.abs['-1']]];           // Still returns 1
Math.abs[Math.abs[Math.abs[Math.abs['-1']]]]; // Still returns 1
6 đều chấp nhận một hàm. Chúng là những ví dụ tuyệt vời về các hàm bậc cao hơn, vì chúng lặp lại trên một mảng và gọi chức năng mà họ nhận được cho từng mục trong mảng.higher order functions, as they iterate over an array and call the function they received for each item in the array.

Vì vậy, bạn có thể làm:

// Here's an example of each
const array = [1, 2, 3];

const mappedArray = array.map[function[element]{
    return element + 1;
}];
// mappedArray is [2, 3, 4]

const reduced = array.reduce[function[firstElement, secondElement]{
	return firstElement + secondElement;
}];
// reduced is 6

const filteredArray = array.filter[function[element]{
    return element !== 1;
}];
// filteredArray is [2, 3]

Chuyển kết quả của các chức năng vào các chức năng khác, hoặc thậm chí tự truyền các chức năng, trong là cực kỳ phổ biến trong mã chức năng. Tôi đã bao gồm lời giải thích ngắn gọn này vì tần suất nó được sử dụng.

Các chức năng này cũng thường được sử dụng vì chúng không thay đổi hàm cơ bản [không thay đổi trạng thái] nhưng hoạt động trên một bản sao của

/// Example of some Math.abs uses
Math.abs['-1'];     // 1
Math.abs[-1];       // 1
Math.abs[null];     // 0


Math.abs[Math.abs[Math.abs['-1']]];           // Still returns 1
Math.abs[Math.abs[Math.abs[Math.abs['-1']]]]; // Still returns 1
7.

2. Tránh khả năng đột biến và tác dụng phụ

Quy tắc thứ hai là để tránh tính đột biến - chúng tôi đã chạm vào một thời gian ngắn này, khi chúng tôi nói về việc hạn chế các thay đổi đối với trạng thái đột biến bên ngoài - và tác dụng phụ.

Nhưng ở đây chúng tôi sẽ mở rộng hơn nữa. Về cơ bản, nó sôi sục về điều này: Đừng thay đổi mọi thứ! Khi bạn đã làm nó, nó là bất biến [không thay đổi theo thời gian].immutable [unchanging over time].

var ages = [12,32,32,53]
ages[1] = 12;  // no!
ages = [];     // no!
ages.push["2"] // no!
Mã này không được viết trong mẫu chức năng.

Nếu một cái gì đó phải thay đổi cho các cấu trúc dữ liệu của bạn, hãy thay đổi một bản sao.

const ages = [12,32,32,53]
const newAges = ages.map[function [age]{
    if [age == 12] { return 20; }
    else { return age; }
}]
Much tốt hơn!

Bạn có thể thấy tôi đã thực hiện một bản sao với những thay đổi cần thiết của tôi không?

Yếu tố này được lặp đi lặp lại nhiều lần. Đừng thay đổi trạng thái!

Nếu chúng ta tuân theo quy tắc đó, chúng ta sẽ sử dụng rất nhiều

for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
1 để chúng ta biết mọi thứ sẽ không thay đổi. Nhưng nó phải đi xa hơn thế. Làm thế nào về bên dưới?

const changingObject = {
    willChange: 10
}

changingObject.willChange = 10;  // no!
delete obj.willChange            // no!

Các thuộc tính của

/// Example of some Math.abs uses
Math.abs['-1'];     // 1
Math.abs[-1];       // 1
Math.abs[null];     // 0


Math.abs[Math.abs[Math.abs['-1']]];           // Still returns 1
Math.abs[Math.abs[Math.abs[Math.abs['-1']]]]; // Still returns 1
9 nên được khóa hoàn toàn.
for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
1 sẽ chỉ bảo vệ bạn khỏi việc khởi tạo biến.

0 sử dụng cấu trúc dữ liệu liên tục

Nếu chúng ta không thể thay đổi trạng thái của các biến toàn cầu, thì chúng ta cần đảm bảo:

  • Chúng tôi tuyên bố các đối số chức năng - bất kỳ tính toán nào bên trong một hàm chỉ phụ thuộc vào các đối số và không phải trên bất kỳ đối tượng hoặc biến toàn cầu nào.
  • Chúng tôi không thay đổi một biến hoặc đối tượng - tạo các biến và đối tượng mới và trả về chúng nếu cần từ một hàm.

Làm cho mã của bạn trong suốt tham chiếu

Khi bạn tuân theo quy tắc không bao giờ thay đổi trạng thái, mã của bạn trở nên minh bạch một cách tham chiếu. Đó là, các cuộc gọi chức năng của bạn có thể được thay thế bằng các giá trị mà chúng đại diện mà không ảnh hưởng đến kết quả.referentially transparent. That is, your function calls can be replaced with the values that they represent without affecting the result.

Như một ví dụ đơn giản về việc kiểm tra xem mã của bạn có minh bạch một cách tham khảo hay không, hãy xem đoạn mã bên dưới:referentially transparent, look at the below code snippet:

1

Bạn sẽ chỉ có thể trao đổi cuộc gọi chức năng đó với

function setAvailability[]{
	available = true;
}
1 mà nó trả về và không có vấn đề gì.

Lập trình chức năng với các biểu thức trong suốt tham chiếu khiến bạn bắt đầu suy nghĩ về mã của mình khác nhau nếu bạn đã quen với định hướng đối tượng.object orientation.

Nhưng tại sao?

Bởi vì thay vì các đối tượng và trạng thái có thể thay đổi trong mã của bạn, bạn bắt đầu có các chức năng thuần túy, không có thay đổi trạng thái. Bạn hiểu rất rõ những gì bạn đang mong đợi chức năng của mình sẽ trở lại [vì nó không bao giờ thay đổi, khi thông thường nó có thể trả về các loại dữ liệu khác nhau tùy thuộc vào trạng thái bên ngoài chức năng].

Nó có thể giúp bạn hiểu dòng chảy tốt hơn, hiểu chức năng đang làm gì chỉ bằng cách lướt qua nó và nghiêm ngặt hơn với trách nhiệm của mỗi chức năng để đưa ra các hệ thống tách rời tốt hơn.

Bạn có thể tìm hiểu thêm về tính minh bạch tham chiếu ở đây.

Đừng lặp đi lặp lại

Hy vọng rằng, nếu bạn đã chú ý đến nay, bạn sẽ thấy chúng tôi không thay đổi trạng thái. Vì vậy, chỉ để rõ ràng

function setAvailability[]{
	available = true;
}
2 vòng lặp đi ra ngoài cửa sổ:

2

Bởi vì chúng tôi đang thay đổi trạng thái của một biến ở đó. Thay vào đó, sử dụng chức năng bậc cao

for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
2.

Thêm các tính năng của lập trình chức năng

Tôi hy vọng tại thời điểm này, bạn có một cái nhìn tổng quan tốt về mã chức năng là gì và không. Nhưng có một số khái niệm cuối cùng được sử dụng rất nhiều trong mã chức năng mà chúng ta phải bao gồm.

Trong tất cả các mã chức năng tôi đã đọc, các khái niệm và công cụ này được sử dụng nhiều nhất và chúng tôi phải bao gồm chúng để có được kiến ​​thức nền tảng của chúng tôi.

Vì vậy, ở đây chúng tôi đi.

Đệ quy trong lập trình chức năng

Có thể trong JavaScript để gọi một hàm từ chính chức năng.

Vì vậy, những gì chúng ta luôn có thể làm:

3 Điều này có thể không phải là một ý tưởng tuyệt vời.

Vấn đề với điều này là nó không hữu ích. Cuối cùng nó sẽ chạy cho đến khi nó gặp sự cố trình duyệt của bạn. Nhưng ý tưởng đệ quy là một chức năng tự gọi mình từ cơ thể chức năng của nó. Vì vậy, hãy xem một ví dụ hữu ích hơn:

4

Đoạn mã này sẽ được tính từ đối số

function setAvailability[]{
	available = true;
}
4 đến đối số
function setAvailability[]{
	available = true;
}
5. Và nó làm như vậy bằng cách gọi lại chức năng của chính nó.

Vì vậy, thứ tự của điều này sẽ trông giống như thế này:

Một ví dụ về ngăn xếp cuộc gọi cho chức năng đệ quy này.

Thêm một trình gỡ lỗi bên trong các khối IF để làm theo điều này nếu nó không có ý nghĩa với bạn. Recursion là một công cụ bạn có thể sử dụng để lặp lại trong lập trình chức năng.

Điều gì làm cho ví dụ đầu tiên và ví dụ thứ hai khác nhau? Cái thứ hai có cái mà chúng ta gọi là "một trường hợp cơ sở". Một trường hợp cơ sở cho phép chức năng cuối cùng ngừng tự gọi vào chính nó. Khi

function setAvailability[]{
	available = true;
}
4 bằng
function setAvailability[]{
	available = true;
}
5, chúng ta có thể ngừng đệ quy. Như chúng ta biết, chúng ta đã tính đến cuối vòng lặp của chúng ta."a base case". A base case lets the function eventually stop calling into itself infinitely. When
function setAvailability[]{
	available = true;
}
4 is equal to
function setAvailability[]{
	available = true;
}
5 we can stop recursing. As we know we have counted to the very end of our loop.

Nhưng mỗi cuộc gọi của các chức năng đang gọi lại chức năng của chính nó và thêm vào đối số chức năng.

Ví dụ mã tôi chỉ đưa vào ví dụ đếm không phải là một hàm thuần túy. Tại sao vậy?pure function. Why is that?

Bởi vì

function setAvailability[]{
	available = true;
}
8 là trạng thái! Và chúng tôi đã đăng nhập ____ 41 của nó.

Đây là một giới thiệu ngắn gọn về đệ quy, nhưng hãy đến đây để tìm hiểu thêm ở đây.

Tại sao sử dụng đệ quy?

Đệ quy cho phép chúng ta ngừng biến đổi các biến trạng thái, cho một.

Ngoài ra còn có một số cấu trúc dữ liệu nhất định [cấu trúc cây] hiệu quả hơn khi được giải quyết với đệ quy. Họ thường yêu cầu ít mã hơn, vì vậy một số lập trình viên thích khả năng đọc của đệ quy.

Currying trong lập trình chức năng

Currying là một công cụ khác được sử dụng rất nhiều trong mã chức năng. Sự khác biệt của một hàm đề cập đến số lượng đối số mà nó nhận được.arity of a function refers to how many arguments it receives.

5


Currying một hàm biến một hàm có độ cao hơn 1, thành 1. Nó thực hiện điều này bằng cách trả về một hàm bên trong để thực hiện đối số tiếp theo. Đây là một ví dụ: a function turns a function that has an arity of more than 1, to 1. It does this by returning an inner function to take the next argument. Here's an example:

6


Về cơ bản, nó tái cấu trúc một hàm để nó có một đối số, nhưng sau đó nó trả về một chức năng khác để lấy đối số tiếp theo, nhiều lần như nó cần.

Tại sao sử dụng cà ri?

Lợi ích lớn của việc cà ri là khi bạn cần sử dụng lại cùng một hàm nhiều lần nhưng chỉ thay đổi một [hoặc ít hơn] các tham số. Vì vậy, bạn có thể lưu cuộc gọi chức năng đầu tiên, một cái gì đó như thế này:

7

Currying cũng có thể làm cho mã của bạn dễ dàng hơn để tái cấu trúc. Bạn không cần phải thay đổi nhiều nơi mà bạn đang vượt qua các đối số chức năng sai - chỉ là một nơi, nơi bạn ràng buộc cuộc gọi chức năng đầu tiên với đối số sai.

Nó cũng hữu ích nếu bạn không thể cung cấp tất cả các đối số cho một chức năng cùng một lúc. Bạn chỉ có thể trả lại chức năng đầu tiên để gọi hàm bên trong khi bạn có tất cả các đối số sau.

Ứng dụng một phần trong lập trình chức năng

Tương tự, ứng dụng một phần có nghĩa là bạn áp dụng một vài đối số cho một hàm tại một thời điểm và trả về một hàm khác được áp dụng cho nhiều đối số hơn. Đây là ví dụ tốt nhất tôi tìm thấy từ các tài liệu MDN:

8

// Here's a non-functional example
const ages = [12,32,32,53]
for [var i=0; i < ages.length; i++] {
    finalAge += ages[i];
}

// Here's a functional example
const ages = [12,32,32,53]
const totalAge = ages.reduce[ function[firstAge, secondAge]{
    return firstAge + secondAge;
}]

0 là ví dụ tốt nhất của một ứng dụng một phần. Tại sao?

Bởi vì chúng tôi trả về một hàm bên trong được gán cho

// Here's a non-functional example
const ages = [12,32,32,53]
for [var i=0; i < ages.length; i++] {
    finalAge += ages[i];
}

// Here's a functional example
const ages = [12,32,32,53]
const totalAge = ages.reduce[ function[firstAge, secondAge]{
    return firstAge + secondAge;
}]

1 được gọi, với phạm vi
// Here's a non-functional example
const ages = [12,32,32,53]
for [var i=0; i < ages.length; i++] {
    finalAge += ages[i];
}

// Here's a functional example
const ages = [12,32,32,53]
const totalAge = ages.reduce[ function[firstAge, secondAge]{
    return firstAge + secondAge;
}]

2 được thiết lập chính xác và một đối số mới được truyền qua sau. Chúng tôi đã không gán tất cả các đối số cùng một lúc, nhưng thay vào đó chúng tôi đã trả lại một hàm để chấp nhận phần còn lại của các đối số.

Tại sao sử dụng ứng dụng một phần?

Bạn có thể sử dụng ứng dụng một phần bất cứ khi nào bạn không thể chuyển tất cả các đối số của mình cùng một lúc, nhưng có thể trả lại

// Here's a non-functional example
const ages = [12,32,32,53]
for [var i=0; i < ages.length; i++] {
    finalAge += ages[i];
}

// Here's a functional example
const ages = [12,32,32,53]
const totalAge = ages.reduce[ function[firstAge, secondAge]{
    return firstAge + secondAge;
}]

3 từ các chức năng bậc cao hơn để đối phó với phần còn lại của các đối số.

Thành phần chức năng trong lập trình chức năng

Chủ đề cuối cùng mà tôi nghĩ là cơ bản của mã chức năng là thành phần chức năng.function composition.

Thành phần chức năng cho phép chúng ta lấy hai hoặc nhiều chức năng và biến chúng thành một hàm thực hiện chính xác những gì hai hàm [hoặc nhiều] làm.allows us to take two or more functions and turn them into one function that does exactly what the two functions [or more] do.

9

Bạn có thể thực hiện điều này xa hơn và tạo các chức năng để soạn bất kỳ số lượng chức năng đa dạng nào với nhau nếu bạn cần điều đó cho trường hợp sử dụng của mình.

Tại sao sử dụng thành phần chức năng?

Thành phần cho phép bạn cấu trúc mã của mình ra khỏi các hàm có thể sử dụng lại, để ngừng lặp lại chính mình. Bạn có thể bắt đầu xử lý các chức năng như các khối xây dựng nhỏ mà bạn có thể kết hợp với nhau để đạt được đầu ra phức tạp hơn.

Chúng sau đó trở thành "đơn vị" hoặc sức mạnh tính toán trong các chương trình của bạn. Chúng có rất nhiều chức năng nhỏ hoạt động chung, tất cả được sáng tác thành các chức năng lớn hơn để thực hiện công việc "thực".

Đó là một cách mạnh mẽ để kiến ​​trúc mã của bạn và ngăn bạn tạo ra các chức năng lớn được sao chép và dán với những khác biệt nhỏ giữa chúng.

Nó cũng có thể giúp bạn kiểm tra khi mã của bạn không được ghép nối chặt chẽ. Và nó làm cho mã của bạn có thể tái sử dụng hơn. Bạn chỉ có thể thay đổi thành phần của các chức năng của mình hoặc thêm các hàm nhỏ hơn vào bố cục, thay vì có tất cả các mã được sao chép và dán tất cả trên cơ sở mã [khi bạn cần nó làm một cái gì đó tương tự nhưng không giống như một hàm khác] .

Ví dụ dưới đây được thực hiện tầm thường để giúp bạn hiểu, nhưng tôi hy vọng bạn thấy sức mạnh của thành phần chức năng.function composition.

for [let i = 0; i < arr.length; i++] {
     increment += arr[i];
}
0

Bạn có thấy cách chúng ta sáng tác các chức năng mới từ các chức năng thuần túy, thuần túy không?

Sự kết luận

Bài viết này bao gồm rất nhiều. Nhưng tôi hy vọng nó đã giải thích mã chức năng một cách đơn giản, cùng với một số mẫu lặp lại mà bạn sẽ thấy nhiều lần, trong mã chức năng và thậm chí không chức năng.

Mã chức năng không nhất thiết là tốt nhất và không phải là mã định hướng đối tượng. Mã chức năng thường được sử dụng cho các vấn đề dựa trên toán học hơn như phân tích dữ liệu. Nó cũng rất hữu ích cho các hệ thống thời gian thực có sẵn cao, như những thứ được viết bằng Erlang [một ngôn ngữ chức năng]. Nhưng nó thực sự không phụ thuộc vào vấn đề.

Tôi đăng bài viết của tôi trên Twitter. Nếu bạn thích bài viết này, bạn có thể đọc thêm ở đó.

Cách tìm hiểu thêm

Bắt đầu từ đây, với phần giới thiệu của Freecodecamp về lập trình chức năng với JavaScript.

Nhìn vào đây cho một số thư viện bạn có thể bao gồm và chơi xung quanh, để thực sự thành công lập trình chức năng.

Xem xét tổng quan tốt này về rất nhiều khái niệm chức năng.

Cuối cùng, đây là một thuật ngữ tuyệt vời về thuật ngữ chức năng.

Học mã miễn phí. Chương trình giảng dạy nguồn mở của Freecodecamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu

JavaScript OOP hay chức năng?

JavaScript có thể hoạt động như một ngôn ngữ theo quy trình và đối tượng. Các đối tượng được tạo theo chương trình trong JavaScript, bằng cách gắn các phương thức và thuộc tính vào các đối tượng trống trong thời gian chạy, trái ngược với các định nghĩa lớp cú pháp phổ biến trong các ngôn ngữ được biên dịch như C ++ và Java.. Objects are created programmatically in JavaScript, by attaching methods and properties to otherwise empty objects at run time, as opposed to the syntactic class definitions common in compiled languages like C++ and Java.

JavaScript là chức năng hay mệnh lệnh?

Tuyên bố vs lập trình bắt buộc Bạn có thể viết JavaScript trong mô hình khai báo hoặc mô hình bắt buộc.Đây là ý nghĩa của mọi người khi họ nói đó là ngôn ngữ đa Paradigm.Đó chỉ là mã chức năng theo mô hình khai báo.

Ngôn ngữ nào là ngôn ngữ chức năng?

Một chương trình chức năng được xây dựng bằng cách áp dụng các chức năng cho các đối số.Các ngôn ngữ chức năng, chẳng hạn như LISP, ML và Haskell, được sử dụng làm công cụ nghiên cứu trong phát triển ngôn ngữ, trong các provers định lý toán học tự động và trong một số dự án thương mại.LISP, ML, and Haskell, are used as research tools in language development, in automated mathematical theorem provers, and in some commercial projects.

Lập trình chức năng JavaScript là gì?

Lập trình chức năng là một mô hình lập trình nơi bạn chủ yếu xây dựng và cấu trúc mã của mình bằng các chức năng.Các chức năng này lấy đầu vào được gọi là đối số sau đó hiển thị đầu ra dựa trên các đầu vào được thực hiện, với cùng một đầu vào luôn luôn dẫn đến cùng một đầu ra.

Bài Viết Liên Quan

Chủ Đề