Javascript是功能编程语言吗?


135

仅仅因为函数是一流的对象,就存在闭包和高阶函数,Javascript是否值得被称为功能编程语言?我认为它缺少的主要功能是纯函数,它不像其他函数语言(如lisp)那样“感觉”(尽管这并不是使其成为功能语言的充分理由……)


12
@slashmais:不!这只会阻止它成为纯功能语言。ML(至少是现代方言)也是不纯正的-但没有人敢称它们不起作用;)

4
有很多语言通常被认为是功能性的,但并不是纯净的。我不知道这是什么要求。如果要严格一点,那么大多数所谓的OOP语言也不是OOP。最后,所有语言中约有95%是无范式语言。
jalf

6
为什么如此重要?当我用C ++编写代码时,我不在乎语言是否为“ OOP”。我关心它具有某些OOP功能,它具有几个功能编程功能,许多命令式编程功能和许多通用编程功能。但是,无论它是“是” OOP语言还是FP语言或其他任何东西都没有关系。同样,当我用JS编写代码时,是否为FP也无关紧要。重要的是它支持许多出色的FP功能。看来这是一个错误的问题。
jalf

3
@hvgotcodes:是吗?绝对没有规则说不是。我的经验法则是,如果您可以使用它以功能样式进行编程,则它是一种功能语言。由于Javascript具有一流的功能,闭包和lambda,因此我相信您可以,就我而言,它是一种功能语言。显然,这并不是一种纯粹的语言,但是我们通常认为FP的大多数语言(例如SML)也并非如此。所以说真的,我想您只需要放松一下。如果那使您的眼睛抽搐,则需要去看医生。
jalf

3
@杰夫,绝对。这个问题的动机是我想知道我的同龄人和比我想象的要聪明的人。
hvgotcodes 2010年

Answers:


180

重复对类似问题的回答,

功能编程语言尚无公认的定义。

如果将功能性语言定义为支持一等函数和lambda的语言,那么可以,JavaScript是一种功能性语言。

如果您还考虑诸如对不变性的支持,代数数据类型,模式匹配,部分应用程序等因素,那么不,JavaScript *不是*功能语言。


我鼓励您阅读以下相关博客文章(以及它们下方的评论):


29
+1表示没有通用定义,并提供了JS没有的原型功能语言功能的一些示例。

1
Mozilla的JavaScript实施的更高版本(以1.7
开头

JavaScript具有局部性和部分应用参数的概念,所以我想知道您不支持这种说法的说法是否正确?
johnbakers

2
@OpenLearner,我几乎能想到的每种语言都支持部分应用程序,甚至包括C。无论如何,对于“支持”的某种定义。JS的情况也是如此。关键是部分应用程序是否毫不费力并且是该语言的一流产品。在JS中不是。如果您对我的意思感到好奇,请查看OCaml或Haskell。
missingfaktor

JavaScript支持不变性afaik。
fka

26

我会说这是一种多范式语言。

编辑:这是多范式,包括功能构造。


是的,我同意这是混合体和一些不同的东西。
Ashley Grenon 2010年

5
但这并不能回答它是否起作用的问题。成为多范式意味着支持多种范式。这些范例之一是功能编程吗?
jalf

15

如果您将术语“函数式编程”延伸或扭曲到哲学讨论的目的,那么这个问题可能会再次公开。但是,然后您遇到了一些有用的问题,例如“ C ++真的是一种编程语言”吗?

每天您的问题的答案是“否”

函数式编程意味着将程序概念化为函数的评估,而不是控制流。该代码是对功能的描述,没有控制流程的固有概念。

JavaScript具有控制流,并被概念化为命令性语言。从其设计目标来看,它显然不是功能语言。


1
设计目标?你什么意思?最后我检查了一下,它的灵感来源之一是Scheme。我得说,很明显,它的设计目标之一是支持函数式编程,以及作为一个箩筐其他范式
jalf

2
如果您自己编写适当的基础,它就和C ++一样支持函数式编程-只需花很少的工作,就可以在Haskell中模拟命令式语法。尽管如此,JavaScript的语法仍使它被认为是一个工作流程,而不是功能的评估。因此,我(或大多数功能程序员)认为应用“功能”一词过于广泛。
shuhalo 2010年

@ user411768:您是说一种语言是否起作用取决于其标准库的设计?我以前从未听过这个定义。Java具有以功能样式(例如,闭包和匿名函数)进行编程所需的大多数工具,而C ++(当前)还没有。我认为这使JS的FP比C ++多得多。语言不会强迫您以FP风格进行编程的事实并不能使其“缺乏功能”,对吗?
jalf

1
(i)正如语法功能一样,标准库是标准的一部分,并强调某种惯用和概念风格。例如,“带有STL的C ++”与“带有类的C”非常不同。有影响。(ii)JavaScript功能具有面向对象的功能,是一等公民功能-这些功能与命令/功能二分法正交。但是,它既不直接实现咖喱,也不提供纯度,也从未打算这样做。(iii)我的遗言,请参阅该帖子的第一段。
shuhalo 2010年

3
JavaScript和C ++提供相同的功能编程便利性的说法肯定是错误的。JavaScript使函数式编程变得非常简单明了,而无需使用C ++中的所有凌乱结构来实现相同的目的。有很多伟大的C ++编码人员着重指出,在C ++中确实不鼓励使用函数式编程,但是有关在JavaScript中进行函数式编程的文章很多
johnbakers

9

如今,术语“函数式编程”语言是如此繁琐,几乎毫无用处。有两个主要含义:

  1. 具有一流的功能
    • Javascript是这个!
  2. 基于lambda演算中使用的函数,重点在于避免持久的可变状态(通常将其替换为传递给函数的参数)
    • 如通常所写,JavaScript并非遥不可及!

选择您的意思,然后问题就可以回答了。


是否有使用“函数式编程”的语言来指代函数是一阶公民的语言?
shuhalo

@ user411768:实际上,另一个链接到Wikipedia文章的回答者使用该定义。en.wikipedia.org/wiki/Javascript — Joel Spolsky在他的“您的编程语言可以做到这一点”中也暗含了此定义。发布“函数式编程”的好处
Chuck

您会注意到,正如通常所写的那样,JavaScript并没有使用第二点,但这当然并不意味着没有程序员完全做到这一点,并且该语言不支持这种功能,因为它确实支持
johnbakers

@OpenLearner:是的,但是Java和许多其他通常被严格认为是必需的语言也是如此-您可以以功能样式编写它们,但这并不是该语言的幸福之路。
Chuck

...但是最新的JS会支持它。
Erik Reppen

3

我不认为函数式编程有一个具体的定义,但是人们认为“函数式编程”的许多事情都可以用javascript完成。这是本文中一个很好的简短示例


2

对我来说,Javascript既是命令式语言又是功能性语言,您可以选择以任何一种方式使用它,甚至可以使用(egad)两种方式使用它。或者,您可以选择使用一种范例,而从不接触另一种。由你决定。我和您一样,不认为Java 语言应被称为功能语言,因为它使您可以进入和离开功能编程范式。我想,也许如果它有某种实用性来限制您仅使用函数式编程范例,那将很有用。但是,总而言之,我说这更多是一种命令式/过程性语言,并引入了一些功能编程功能。


通过这种推理,F#不再可以称为函数。
埃里克·米克尔森

1
对。根据Wikipedia的说法,F#就是我刚才所说的Javascript:“ F#是一种多范式编程语言,其中包含函数式编程以及命令式面向对象编程学科”
Brian Onn

2

我倾向于不认为编程语言具有一种特定的范例,而是它们适合某些范例。但是,仅仅因为它们适合特定的范例并不意味着您必须使用该范例。很有可能用C编写面向对象的程序,并用ML编写命令式程序。不使用某种范例来解决问题,因为该语言不是针对该语言而设计的,而是人为地限制了自己(当然,在确定某个特定的解决方案是否是一个好的解决方案时,您仍然应该考虑语言的局限性)。


0

好吧,我不会说这是函数式编程,但是我说它是面向对象的,直到今天,一个朋友说他也不会把它放在那个架子上。

因此,虽然我不会说是,但我认为仍有意见余地。它确实具有函数式编程的经典功能,没有其他功能。


2
JavaScript是面向对象的。OO不需要类,但是需要对象。
隐身

3
Javascript不是面向对象的,它是基于原型的。
克里斯(Kris)2014年

1
JavaScript是编程的汤。这一点和那一点。
安德鲁S

0

Java语言是有道理的。这确实取决于您如何进行编程。如果我以面向对象的方式编写代码,那不是面向对象的吗?因此,如果您仅以“功能性”方式编写代码,那么它将是功能性的。我猜这是多范式语言,所以仅称之为一件事并不完全准确。


0

@petraszd我重写代码一点,以获得一个“新” 操作:

   
   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]())
   })

但是我知道这种方式对大循环不利。

有关JS中的尾部递归优化的相关问题

PS张贴在这里,因为发表评论时,代码格式有问题


0

在Javascript中,您可以执行以下操作!

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

为了演示这个概念,我制作了一个github页面,您可以克隆/查看我的实现。


0

众所周知,函数式编程语言不允许更改或变异函数的元素(状态),但是在javascript中,虽然函数式语言将函数视为一等公民,但从某种意义上讲,它不是函数式编程语言。


-2

我真正讨厌javascript(如果您尝试将其视为FP语言)的是:

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

您需要了解JS堆栈环境(如果它是正确的术语,我就不需要)以了解这种行为。

例如,在方案中,您只是无法产生这种东西(好吧,好吧-借助基础语言的引用,您可以做到):

(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
嗯,我认为Javascript保留对变量的引用,但不保留对value的引用。
aeracode 2012年

1
了解变量作用域对于使用任何语言进行有效编程至关重要。在这方面,JavaScript并不孤单。
rich remer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.