Javascript có phải là ngôn ngữ lập trình chức năng không?


135

Chỉ vì các hàm là các đối tượng hạng nhất, có các bao đóng và các hàm bậc cao hơn, Javascript có xứng đáng được gọi là ngôn ngữ Lập trình hàm không? Điều chính tôi nghĩ nó thiếu là Chức năng thuần túy và nó không "cảm thấy" như các ngôn ngữ chức năng khác, như lisp (mặc dù đó không thực sự là một lý do chính đáng để nó không phải là một ngôn ngữ chức năng ...)


12
@slashmais: Không! Điều đó chỉ ngăn nó là một ngôn ngữ chức năng (ly) thuần túy. ML (ít nhất là phương ngữ hiện đại) cũng không trong sạch - nhưng không ai dám gọi chúng là không hoạt động;)

4
Có rất nhiều ngôn ngữ thường được coi là chức năng, nhưng không phải là ngôn ngữ thuần túy. Tôi không thấy đó là một yêu cầu. Nếu bạn muốn nghiêm khắc như vậy, thì hầu hết các ngôn ngữ OOP cũng không phải là OOP. Bạn kết thúc với khoảng 95% tất cả các ngôn ngữ là ngôn ngữ không có mô hình.
jalf

6
Tại sao nó quan trọng mặc dù? Khi tôi viết mã bằng C ++, tôi không quan tâm liệu ngôn ngữ "có phải là OOP" hay không. Tôi quan tâm rằng nó có một số tính năng OOP nhất định và nó có một vài tính năng lập trình chức năng, và rất nhiều tính năng lập trình bắt buộc và rất nhiều tính năng lập trình chung. Nhưng cho dù đó là "ngôn ngữ OOP" hay ngôn ngữ FP hay thứ gì khác không quan trọng. Tương tự như vậy khi tôi viết mã trong JS, nó không thành vấn đề nếu đó là FP hay không. Điều quan trọng là nó hỗ trợ rất nhiều tính năng FP đẹp. Có vẻ như đây là câu hỏi sai.
jalf

3
@hvgotcodes: vậy? Hoàn toàn không có quy tắc nói rằng nó không phải. Nguyên tắc nhỏ của tôi là nó là một ngôn ngữ chức năng nếu bạn có thể sử dụng nó để lập trình theo kiểu chức năng. Vì Javascript có các chức năng hạng nhất, đóng và lambdas, tôi tin rằng bạn có thể, và theo như tôi nghĩ, đó là một ngôn ngữ chức năng. Rõ ràng không phải là một ngôn ngữ thuần túy, nhưng hầu hết các ngôn ngữ chúng ta thường coi là FP (chẳng hạn SML chẳng hạn). Vì vậy, thực sự, tôi nghĩ rằng bạn chỉ cần nới lỏng. Nếu điều đó làm cho mắt bạn co giật, bạn cần đi khám bác sĩ.
jalf

3
@jalf, hoàn toàn. Động lực cho câu hỏi là tôi muốn biết những gì đồng nghiệp của tôi và những người thông minh hơn tôi nghĩ.
hvgotcodes

Câu trả lời:


180

Lặp lại câu trả lời của riêng tôi cho một câu hỏi tương tự,

Không có định nghĩa được chấp nhận của ngôn ngữ lập trình chức năng.

Nếu bạn định nghĩa ngôn ngữ chức năng là ngôn ngữ hỗ trợ các chức năng hạng nhất và lambdas, thì có, JavaScript * là * một ngôn ngữ chức năng.

Nếu bạn cũng xem xét các yếu tố như hỗ trợ tính bất biến, kiểu dữ liệu đại số, khớp mẫu, ứng dụng một phần, v.v. thì không, JavaScript * không phải là * ngôn ngữ chức năng.


Tôi khuyến khích bạn đọc các bài đăng trên blog có liên quan sau đây (và cả các bình luận bên dưới chúng):


29
+1 để chỉ ra rằng không có định nghĩa phổ quát và mang lại một số ví dụ về các tính năng ngôn ngữ chức năng nguyên mẫu mà JS không có.

1
Các phiên bản sau này của việc triển khai JavaScript của Mozilla (bắt đầu bằng 1.7) có khớp mẫu theo hình thức hủy bài tập: developer.mozilla.org/en/New_in_JavaScript_1.7#section_20
jbeard4

JavaScript có khái niệm về các phần và áp dụng một phần các tham số, vì vậy tôi tự hỏi liệu tuyên bố của bạn rằng nó không hỗ trợ điều này có sai không?
johnbakers

2
@OpenLearner, ứng dụng một phần được hỗ trợ bởi hầu hết mọi ngôn ngữ tôi có thể nghĩ ra, thậm chí C. Đối với một định nghĩa nhất định về "hỗ trợ" nào. Trường hợp với JS không khác. Vấn đề là liệu ứng dụng một phần có dễ dàng và hạng nhất trong ngôn ngữ đó hay không. Trong JS, nó không phải là. Nếu bạn tò mò về ý của tôi, hãy xem OCaml hoặc Haskell.
missingfaktor

JavaScript hỗ trợ bất biến afaik.
fka

26

Tôi muốn nói rằng đó là một ngôn ngữ đa mô hình.

EDIT: Đó là đa mô hình và bao gồm các cấu trúc chức năng.


vâng, tôi đồng ý đó là sự pha trộn và một vài thứ khác nhau.
Ashley Grenon

5
nhưng điều đó không trả lời cho câu hỏi liệu nó cũng có chức năng hay không. Là đa mô hình ngụ ý hỗ trợ nhiều mô hình. Là một trong những mô hình chức năng lập trình?
jalf

15

nếu bạn kéo dài và xoay thuật ngữ "lập trình chức năng" đến điểm thảo luận triết học, câu hỏi này có thể được mở lại. Tuy nhiên, sau đó bạn kết thúc ở mức độ các câu hỏi hữu ích như "C ++ có thực sự là ngôn ngữ lập trình" không?

Câu trả lời cho câu hỏi của bạn ở cấp độ hàng ngày nhiều hơn là "không" .

Lập trình hàm có nghĩa là chương trình được khái niệm hóa như là một đánh giá của một hàm, chứ không phải là một luồng điều khiển. Mã này là một mô tả về các chức năng và không có khái niệm vốn có của một luồng điều khiển.

JavaScript có một luồng điều khiển và được khái niệm hóa như một ngôn ngữ bắt buộc. Từ mục tiêu thiết kế của nó, rõ ràng nó không phải là một ngôn ngữ chức năng.


1
Mục tiêu thiết kế? Ý anh là gì? Lần cuối tôi kiểm tra, một trong những nguồn cảm hứng của nó là Scheme. Tôi muốn nói nó khá rõ ràng rằng một trong những mục tiêu thiết kế của nó là để hỗ trợ chức năng lập trình cũng như một xô mô khác
jalf

2
Nó hỗ trợ lập trình chức năng nhiều như C ++, nếu bạn tự viết các nền tảng phù hợp cho việc này - nhiều như bạn có thể mô phỏng cú pháp bắt buộc trong, giả sử, Haskell với một công việc nhỏ. Tuy nhiên, cú pháp của JavaScript dẫn đến việc nó được nghĩ về một luồng công việc thay vì đánh giá một hàm. Vì lý do đó, tôi (hoặc hầu hết các lập trình viên chức năng) coi việc áp dụng thuật ngữ "chức năng" là quá rộng rãi.
shuhalo

@ user411768: vậy bạn có nói rằng ngôn ngữ có chức năng hay không phụ thuộc vào thiết kế của thư viện chuẩn của nó? Tôi chưa bao giờ nghe nói rằng định nghĩa trước. Java có hầu hết các công cụ cần thiết để lập trình theo kiểu chức năng (chẳng hạn như các hàm đóng và ẩn danh), mà C ++ (hiện tại) không có. Tôi nghĩ rằng điều đó làm cho JS nhiều FP hơn C ++. Thực tế là ngôn ngữ không buộc bạn phải lập trình theo kiểu FP không làm cho nó "ít chức năng" hơn, phải không?
jalf

1
(i) Thư viện tiêu chuẩn là một phần của tiêu chuẩn, giống như các tính năng cú pháp, và nhấn mạnh một phong cách thành ngữ và khái niệm nhất định. Ví dụ: "C ++ với STL" rất khác với "C với các lớp". Nó có tác động. (ii) JavaScript có tính năng định hướng đối tượng, chức năng công dân hạng nhất - các tính năng này khá trực giao với sự phân đôi không hoàn hảo / chức năng. Tuy nhiên, nó không trực tiếp thực hiện cà ri, cũng không cung cấp độ tinh khiết, cũng không bao giờ được dự định cho việc này. (iii) Những từ cuối cùng của tôi về điều đó, xem đoạn đầu tiên của bài viết.
shuhalo

3
Tuyên bố rằng JavaScript và C ++ cung cấp các tiện ích lập trình chức năng giống nhau chắc chắn là sai. JavaScript làm cho lập trình chức năng khá đơn giản và đơn giản mà không cần tất cả các cấu trúc lộn xộn mà bạn phải trải qua trong C ++ để đạt được điều tương tự. Có rất nhiều lập trình viên C ++ tuyệt vời nói rằng lập trình hàm thực sự không được khuyến khích trong C ++, tuy nhiên các bài viết về lập trình chức năng trong JavaScript rất phong phú
johnbakers

9

Thuật ngữ "lập trình chức năng" ngày nay quá tải, nó gần như vô dụng. Có hai ý nghĩa chính:

  1. Có chức năng hạng nhất
    • Javascript là thế này!
  2. Được dựa trên các hàm như được sử dụng trong phép tính lambda, nhấn mạnh vào việc tránh trạng thái đột biến liên tục (thường thay thế nó bằng các tham số được truyền cho các hàm)
    • Như thường được viết, Javascript không phải là từ xa này!

Chọn ý nghĩa của bạn và sau đó câu hỏi là có thể trả lời.


Có nguồn nào sử dụng "lập trình chức năng" để chỉ các ngôn ngữ có chức năng là công dân bậc nhất không?.
shuhalo

@ user411768: Trên thực tế, một người trả lời khác được liên kết với bài viết của Wikipedia, sử dụng định nghĩa đó. vi.wikipedia.org/wiki/Javascript - Joel Spolsky cũng ngụ ý định nghĩa này trong "Ngôn ngữ lập trình của bạn có thể làm điều này?" bài viết về lợi ích của "lập trình chức năng"
Chuck

Bạn lưu ý rằng, như thường được viết, JavaScript không sử dụng điểm thứ hai của bạn, nhưng điều đó chắc chắn không có nghĩa là không có lập trình viên làm chính xác điều đó và ngôn ngữ không hỗ trợ tính năng như vậy, bởi vì nó chắc chắn
johnbakers

@OpenLearner: Vâng, vâng, nhưng điều tương tự cũng đúng với Java và rất nhiều ngôn ngữ khác thường được coi là bắt buộc - bạn có thể viết chúng theo phong cách chức năng, nhưng đó không phải là con đường hạnh phúc của ngôn ngữ.
Chuck

... nhưng JS mới nhất sẽ hỗ trợ nó.
Erik Reppen

3

Tôi không nghĩ có một định nghĩa cụ thể về lập trình chức năng, tuy nhiên nhiều điều mọi người cho là "lập trình chức năng" có thể được thực hiện bằng javascript. Dưới đây là một ví dụ ngắn gọn trong bài viết này.


2

Đối với tôi, Javascript vừa là ngôn ngữ bắt buộc vừa là ngôn ngữ chức năng và bạn có thể chọn sử dụng nó theo bất kỳ cách nào và thậm chí ( egad ) cả hai cách. Hoặc bạn có thể chọn sử dụng một mô hình và không bao giờ chạm vào mô hình kia. Tuỳ bạn. Tôi cũng như bạn, đừng nghĩ Javascript nên được gọi là Ngôn ngữ chức năng, bởi vì nó cho phép bạn đi lang thang trong và ngoài mô hình lập trình chức năng. Có lẽ nếu nó có một loại pragma nào đó, để hạn chế bạn chỉ sử dụng các mô hình lập trình chức năng, thì điều đó sẽ hữu ích, tôi nghĩ vậy. Nhưng, tóm lại, tôi nói nó giống ngôn ngữ bắt buộc / thủ tục hơn với một số tính năng lập trình chức năng được đưa vào.


Theo lý do đó, F # không thể được gọi là chức năng.
Eric Mickelsen

1
Đúng. Theo Wikipedia, F # chính xác là cái mà tôi vừa gọi là Javascript: "F # [...] là ngôn ngữ lập trình đa mô hình [...] bao gồm lập trình chức năng cũng như các môn lập trình hướng đối tượng bắt buộc"
Brian Onn

2

Tôi có xu hướng không nghĩ rằng các ngôn ngữ lập trình là có một mô hình cụ thể, nhưng chúng cho vay theo một số mô hình nhất định. Tuy nhiên, chỉ vì họ cho vay một mô hình cụ thể không có nghĩa là bạn phải sử dụng mô hình đó. Hoàn toàn có thể viết các chương trình hướng đối tượng trong C và viết các chương trình bắt buộc trong ML. Không sử dụng một mô hình nhất định để giải quyết vấn đề vì ngôn ngữ không được thiết kế cho nó chỉ tự giới hạn một cách giả tạo (tất nhiên bạn vẫn nên tính đến những hạn chế của ngôn ngữ khi quyết định xem một giải pháp cụ thể sẽ là một giải pháp tốt).


0

Chà, tôi sẽ không nói đó là lập trình chức năng, nhưng sau đó tôi sẽ nói nó hướng đối tượng và hôm nay một người bạn nói rằng anh ta cũng sẽ không đặt nó lên kệ đó.

Vì vậy, trong khi tôi sẽ không nói như vậy, tôi đoán có chỗ cho ý kiến. Nó có các tính năng cổ điển của lập trình chức năng, nó không có các tính năng khác.


2
JavaScript là hướng đối tượng. OO không yêu cầu các lớp, tuy nhiên nó yêu cầu các đối tượng.
Ẩn danh

3
Javascript không hướng đối tượng, nó dựa trên nguyên mẫu.
Kris

1
JavaScript là súp lập trình. Một chút về điều này và một chút về điều đó.
Andrew S

0

Javascript là một điểm. Nó thực sự phụ thuộc vào cách bạn đi về lập trình nó. Nếu tôi viết mã theo cách OO, nó sẽ không phải là OO? Vì vậy, nếu bạn chỉ mã hóa mọi thứ theo cách 'chức năng' thì nó sẽ hoạt động. Tôi đoán đó là ngôn ngữ đa mô hình nên để gọi nó chỉ là một thứ không hoàn toàn chính xác.


0

@petraszd Tôi viết lại mã của bạn một chút để có được "mới" cho toán tử:

   
   function ffor(a, b, f){
     function it(i){
       if(i > b)return
       f(i)
       it(i+1)
     }
     it(a)
   }

   print("----" + new Date()+"----")

   var funcs = []
   ffor(0, 9, function(i){
     funcs.push(function(){return i})
   })

   ffor(0, 9, function(i){
     print(funcs[i]())
   })

Nhưng tôi biết rằng cách này có nhược điểm đối với các vòng lặp lớn ...

Câu hỏi liên quan về tối ưu hóa hồi quy đuôi trong JS

PS đăng ở đây vì có vấn đề với định dạng mã trong khi đăng dưới dạng bình luận


0

Trong Javascript, bạn có thể làm một cái gì đó như thế này !!

// Data
var fruits = [
    { name: 'apple',  price: 5 }, 
    { name: 'orange', price: 10 }, 
    { name: 'lemon',  price: 15 }
]

// Request Data from magicURL
request('magicURL')
    .then(selectKeyOf('price'))
    .then(priceMethod('sum'))
    .then((result)=>{
        console.log(result) // 30
    })

Tôi đã tạo một trang github để demo khái niệm này và bạn có thể sao chép / xem triển khai của tôi


0

Như chúng ta biết, ngôn ngữ lập trình chức năng không cho phép thay đổi hoặc biến đổi các thành phần (trạng thái) của chức năng nhưng trong javascript, nó được cho phép theo nghĩa đó không phải là ngôn ngữ lập trình chức năng, mặc dù nó coi chức năng là công dân hạng nhất.


-2

Điều tôi thực sự ghét trong javascript (nếu bạn cố gắng xem nó như ngôn ngữ FP) là:

function getTenFunctionsBad() {
  var result = [];
  for (var i = 0; i < 10; ++i) {
    result.push(function () {
      return i;
    });
  }
  return result;
}

function getTenFunctions() {
  var result = [];
  for (var i = 0; i < 10; ++i) {
    result.push((function (i) {
      return function () {
        return i;
      }
    })(i));
  }
  return result;
}

var functionsBad = getTenFunctionsBad();
var functions = getTenFunctions()
for (var i = 0; i < 10; ++i) {
  // using rhino print
  print(functionsBad[i]() + ', ' + functions[i]());
}

// Output:
//   10, 0
//   10, 1
//   10, 2
//   10, 3
//   10, 4
//   10, 5
//   10, 6
//   10, 7
//   10, 8
//   10, 9

Bạn cần hiểu môi trường ngăn xếp JS (tôi không biết nếu đó là thuật ngữ đúng) để hiểu hành vi như vậy.

Ví dụ, trong sơ đồ Bạn không thể tạo ra những thứ như vậy (Ok, ok - với sự trợ giúp của các tài liệu tham khảo của các ngôn ngữ cơ bản Bạn có thể thực hiện):

(define (make-ten-functions)
  (define (iter i)
    (cond ((> i 9) '())
          (else (cons (lambda () i) (iter (+ i 1))))))
  (iter 0))

(for-each (lambda (f)
            (display (f))
            (newline)) (make-ten-functions))

1
Hừm, tôi nghĩ Javascript giữ tham chiếu đến biến nhưng không giữ tham chiếu đến giá trị .
aeracode

1
Hiểu phạm vi biến là rất quan trọng để lập trình hiệu quả trong bất kỳ ngôn ngữ. Javascript không đơn độc trong việc này.
người làm giàu giàu
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.