Javascript是一种功能编程语言吗


34
  • Javascript是功能语言吗?我知道它有对象,您也可以用它进行OOP,但是它也是一种功能语言,可以这样使用吗?
  • 您知道OOP如何/似乎像编程的下一个演变一样,是否意味着“功能性编程”是下一个发展(注意:这不是提意见的提示,而是基于事实证据的答案的提示,并且本说明是主持人比贡献者更多;))。
  • 我通过示例学习得最好,也许有人可以展示以OOP方式执行相同的任务,然后以功能编程的方式让我自己理解和比较功能编程的作用。

老实说,我并不完全理解“函数式编程”:P因此,将Javascript与函数式编程进行比较可能完全不正确。

用外行人的话来描述函数式编程:仅仅是使用匿名函数进行摘要的好处吗?

还是这样简单?通过简单的方法,OOP是通过对象进行抽象的好处,但是我认为描述OOP有点过于简单。

这是函数式编程的一个很好的例子吗?...

Javascript OOP示例:

// sum some numbers
function Number( v )
{ 
  this.val = v;
}

Number.prototype.add( /*Number*/ n2 )
{
    this.val += n2.val;
}

函数式编程示例:

function forEach(array, action) 
{
   for (var i = 0; i < array.length; i++)
       action(array[i]);
}  

function add(array)
{
    var i=0;
    forEach(array, function(n)
    {
        i += n;
    });
    return i;
}

var res = add([1,9]);

它取决于“功能编程语言”的定义。从广义上讲,可以理解为使用封闭值构建功能值的能力,即具有“ lambda”构造(在lambda微积分的意义上),然后Javascript符合要求的能力。
Basile Starynkevitch 2011年

2
Or is that way too simple?是的,是。匿名函数有时与功能语言和支持函数式编程的多范式语言相关联,但是它们并不是功能语言的独特特征。但是,如果您将它们视为λ演算的实现,那么它们就是函数式编程的核心部分,主要要点是,它并不是那么简单:)
yannis 2011年

Javascript的设计阻止了实现能够进行尾部调用优化。在我的书中,仅此一项就无法将其标记为功能。
dan_waterworth 2012年

I know it has objects & you can do OOP with it also不,你不能。它是基于原型的编程,消除了类和对象之间的区别。我个人认为基于原型的编程在此基本级别上存在缺陷。
RokL 2012年

Javascript不是一种功能语言,可以肯定的是它具有功能特性,但是良好的古老命令式C也是如此。实际上每种语言都具有基本功能特性。纯函数式语言(例如Haskell,ML等)是说明性语言,而不是命令性语言。
ALXGTV

Answers:


72

Javascript是功能语言吗?我知道它有对象,您也可以用它进行OOP,但是它也是一种功能语言,可以这样使用吗?

有时,当人们指的是命令式编程过程式编程时,人们会说函数编程。严格来说,函数式编程是:

在计算机科学中,函数式编程是一种编程范例,将计算视为对数学函数的评估,并避免了状态数据和可变数据。与强调状态变化的命令式编程风格相反,它强调函数的应用。函数式编程起源于lambda演算,lambda演算是一种1930年代开发的正式系统,用于研究函数定义,函数应用程序和递归。许多函数式编程语言可以看作是lambda演算的精妙之处。

尽管Javascript尚未广为人知或用作功能语言,但它确实具有一些功能元素

JavaScript与Scheme有很多共同点。它是一种动态语言。它具有灵活的数据类型(数组),可以轻松模拟s表达式。最重要的是,功能是lambda。

SchemeLisp的方言,可能是大多数程序员在讨论函数式编程时所想到的语言之一。当谈到面向对象时,JavaScript是一种面向对象的语言。但是其面向对象是基于原型的

基于原型的编程是一种面向对象的编程风格,其中不存在类,并且行为的重用(在基于类的语言中称为继承)是通过克隆用作原型的现有对象的过程来执行的。该模型也可以称为无类,面向原型或基于实例的编程。委托是支持基于原型的编程的语言功能。

因此,尽管Javascript是面向对象的,但它并没有遵循更常见的基于类的模型,C ++,C#,Java和PHP(以及许多其他语言)也没有。当然,它也是命令式语言,这导致了与我上面描述的函数式编程的混淆。

您知道OOP是如何变成/似乎像编程的下一个进化,这是否意味着“功能编程”是下一个进化

面向对象和函数式编程只是许多不同编程范例中的两种,它们是具有不同概念和抽象的不同编程风格。关键字是“不同”。没有哪个范式比其他范式更好,或者比其他范式更进化,每个范式都比其他场景更适合某些场景。有些可能比其他的起源更早,但是从进化的角度来看,它们的存活时间更长,因此变得更好。但这不是一个非常聪明的观察方法。

正如我上面所描述的,JavaScript和其他许多语言是多范式的。它允许您以命令式,基于原型的面向对象和功能风格编写代码。由您自己选择最适合您所构建的建筑物。还有几种单一的范例语言,典型的例子是Java,它仅允许基于类的面向对象编程1

您应该真正抵制将语言和范例视为时尚陈述的任何冲动。那里有很多废话,主要是由歌迷/歌迷或行销人员撰写的,对编程的知识和了解很少(如果有的话)。像“更好”,“更进化”之类的术语根本不适用。

我通过示例学习得最好,也许有人可以展示以OOP方式执行相同的任务,然后以功能编程的方式让我自己理解和比较功能编程的作用。

那将是一种可怕的学习方式。功能和面向对象的样式是完全不同的样式,除了非常简单的样式以外,任何示例都不适合另一种样式。

1但最近尝试将其范围扩展到泛型编程,让我们看看如何进行。


结论:

  • 专注于学习Javascript,它是一种美丽而极端有用的语言。学习语言,而不是炒作。
  • 有许多不同的范例,它们都同样有用。由您自己选择最喜欢的一个,最适合您正在构建的哪个。
  • 如果您想学习函数式编程,请选择一种更合适的语言,例如Scheme或Clojure。但是,您首先需要了解所涉及的数学概念。
  • 在问之前先做一些研究。有关维基百科的文章回答了您的大多数问题。对于任何程序员而言,知道如何研究和如何提出问题都是一项极其重要的技能。

5
+1好评。由于编程教育的结构方式,新编码人员似乎认为范例是排他的和离散的,但事实并非如此。尝试编写在有意义的情况下利用功能概念的OOP代码。事件驱动的编程是一个范例,但是EDP的某些方面肯定会影响每个GUI和Web程序。多态性是OOP的核心功能,实际上是通用编程。命名这些想法有助于我们将好的编程概念化,但是您不应将其中的一个排除在其他想法之外。
kojiro 2011年

尽管最初的问题和您的答案描述的是Javascript及其与函数式编程的关系,但我认为您的答案是我所看到的OO与函数式编程之间更好的比较之一。做得好。
另一个开发人员,

“这真是一种糟糕的学习方式。”我刚读完这本书,就提出了一个问题,并用一系列范式(包括OOP和FP样式)解决了这本书:github.com/crista/exercises-in-programming-style。我从中学到了很多!
尼克

@nick那只能说明你是什么范式样子,怎么它的工作原理,但它不会告诉你为什么,这可以说是最重要的方面。但是,您需要学习如何才能理解原因:)有时我们会忘记这些事情是一个过程。
马修·布伦特

8

Javascript可以用作功能语言,实际上它做得很好。有可能实现monad支持lambda构造等。它不是唯一的功能语言,因为它还具有许多面向对象的功能,但可以以这种方式使用。实际上,我发现将Javascript作为功能语言是一种很好的使用方式。(示例jQuery和underscore.js)


好而简洁!同意函数式编程通常是在js中完成工作的最简单方法。
bunglestink 2011年

比monad更有趣的是,您可以实现箭头的是JS(cs.umd.edu/projects/PL/arrowlets)。现在,关于为什么有人想要 JavaScript中的箭头,这是一个悬而未决的问题。但这是可以完成的。
rtperson 2012年

我承认我对箭头了解不多,无法知道它们是否有用。但我工作的一本书上单子在Javascript和可加上箭头的一章(shop.oreilly.com/product/0636920023890.do
扎卡里ķ

6

进化通常意味着逐渐的变化。OOP并不是对过程编程的增量添加-实际上,它与底层编程模型完全正交,并且可以与其中任何一个组合。函数式编程不是对过程,OOP或其他任何东西的增量添加-它是 表达基本计算原理的替代基础,实际上,这是 有史以来第一个这样的基础,很早就出现了第一台计算机。重要的是要理解所有这些基本系统都是等效的(即,一个系统可以用另一个系统表示)。

为了理解功能性方法,您需要首先获得基本数学知识。如果您想了解以Java 的功能样式进行编码的含义,请开始使用jQuery


2

没有。

JavaScript首先是一种面向对象的语言。

这并不是说您不能以功能样式编写JavaScript程序,因为如果您努力尝试,则可以采用任何 Turing完整语言采用功能样式。如果愿意,可以在汇编器中进行函数式编程。但这并没有让所有的语言功能。您也可以将Haskell命令式或Java语言称为逻辑编程语言-如果您采用这种方法,则这些术语将很快变得毫无意义。

IMO将语言分类为适当范例的方法是考虑:

  • 语言构造所支持的主要样式是什么(显然,JavaScript面向对象,功能语言则强调函数和不可变的数据值)
  • 语言的核心库支持什么范式(同样显然是针对JavaScript的OOP)
  • 语言禁用或不鼓励使用哪些功能(不鼓励或禁止使用可变功能的可变变量,JavaScript并非如此)
  • 在使用该语言的开发人员社区中,哪种开发风格很普遍(同样,OOP在JavaScript世界中很普遍)

就我个人而言,我发现很多人喜欢声称某种语言具有“功能性”,这是很有趣的,因为这是目前的流行术语:-)

如果您想通过这些年来对编程范例有一个漫长而有趣的观点,那么值得观看Bob Martin叔叔的视频“ The Last Programming Language”。对我来说,这次演讲的深刻见解是编程范式是由它们带走的功能而不是它们所带的功能来定义的……


What is the dominant style enabled by the language constructs我敢于尝试将其应用于Perl ...或您的其他观点,真的:)
yannis 2012年

2
Perl?好挑战!从某种意义上说,它有点像汇编语言,因为您可以一起破解几乎所有想要的范例,但是在我所看到的(脚本)通用用法中,它主要用作命令式/过程式语言。
mikera 2012年

好吧,oop也很常见。当然可以。并且,功能虽然不常见。perl只是perl,试图使其变得没有意义:)
yannis 2012年

JavaScript的功能要比Java稍微强一点,因为它至少具有闭包和一流的功能。但是您的权利,JavaScript和C#一样功能。
雷诺斯(Raynos)2012年

2

Javascript是原型的第一位,具有功能性功能-通过将功能性用作第一类对象来授予它。

这意味着您可以将函数用作数据,这具有减少对保持状态的变量的需求的奇妙效果。如果发现自己想要使用var语句,或者正在使用一个或多个“ if”语句,那么您正在偏离一种功能样式。

函数样式的另一个值得注意的特质是函数应仅返回其求值结果,并且对超出其范围的状态没有副作用:

// oops, this is producing a side effect
function sideEffecter(){//theres no input...        
    window.thingy = 'foo';
    // hey, this isn't returning anything!!!
} 

功能语言是非破坏性的-意味着它们不会改变输入,而是根据输入返回全新的数据。看到这个线程:https : //stackoverflow.com/questions/749084/jquery-map-vs-each

函数式语言还具有许多共同的方法-使用诸如“ map”,“ fold”,“ reduce”之类的名称来处理列表/集合。在JS中,与其他语言不同,我们必须手动将它们变为现实-参见underscore.js之类的以获取一些示例,尽管JS的最新实现可以直接使用其中的一些。

重要的是要记住(IMO),尽管JS可以利用一些功能模式,但执行起来并不总是那么合适。

以迭代数组为例。您可以使用功能样式或本机循环结构来执行此操作-一般而言,循环性能更高。举个例子-用增加大小的循环打它,并在不同的浏览器中记录执行时间(我已经这样做了,但是我失去了基准测试-对不起!):

var test = ['foo', 'bar', 'baz'], removeFunc, removeLoop;

//(semi)functional style...
// to be really functional each condition in the ternary would be another function
removeFunc = function(src, trg) {
    return src.length === 0 ? 
        src : 
            src[0] === trg ? 
                src.slice(1) : 
                    [src[0]].concat(removeFunc(src.slice(1), trg));
};

//but this is faster
removeLoop = function(src, trg){
    var len = src.length, // using variables to represent state...
        i=0, 
        result = [];        
    while(i < n){
       if(src[i] !== trg){
          result.push(src[i]);
       }
       i = i+1;
    }
}

此外,如果您使用功能性结构来敲打相当大的循环,并且不使用某种形式的临时堆栈管理,则可能会淹没堆栈(尽管为了公平起见,您需要一个BIG列表来进行此操作。 ..)。您还必须综合考虑每种浏览器中的变体优化-尽管如果您在Node.js环境中工作,那么这显然更是一个固定的目标。

这并不是说您不应该在Javascript中使用功能结构-只是要意识到相对于其环境而言,其实现方面的限制。

以下是您可能感兴趣的一些链接:

出色的“口才Javascript”中有关Javascript函数式编程的精彩章节

小计划者

我的一个朋友写了一个基于Little Schemer的JS库

关于Scheme的优秀教程,可以帮助您更好地理解FP

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.