基于函数式编程的 JavaScript 应用程序是如何布局的?

发布于 2024-08-29 18:14:26 字数 983 浏览 8 评论 0原文

我在聊天应用程序上使用 node.js 一段时间了(我知道,非常原创,但我认为这将是一个很好的学习项目)。 Underscore.js 提供了很多看起来很有趣的函数式编程概念,所以我想了解如何将设置 JavaScript 中的功能程序。

根据我对函数式编程的理解(这可能是错误的),整个想法是避免副作用,基本上是有一个函数更新函数外部的另一个变量,这样

var external;
function foo() {
   external = 'bar';
}
foo();

就会产生副作用,对吗?因此,作为一般规则,您希望避免全局范围内的干扰变量。

好的,那么当你处理对象时它是如何工作的,而不是什么呢?例如,很多时候,我会有一个构造函数和一个初始化对象的 init 方法,如下所示:

var Foo = function(initVars) {
   this.init(initVars);
}

Foo.prototype.init = function(initVars) {
   this.bar1 = initVars['bar1'];
   this.bar2 = initVars['bar2'];
   //....
}

var myFoo = new Foo({'bar1': '1', 'bar2': '2'});

所以我的 init 方法是故意造成副作用的,但是处理相同情况的函数式方法是什么?

另外,如果有人能给我指出一个程序的 Python 或 JavaScript 源代码,该程序试图尽可能地发挥功能,那我也将不胜感激。我觉得我已经接近“明白”了,但我只是还没有完全做到。我主要感兴趣的是函数式编程如何与传统的 OOP 类概念一起工作(或者如果是这样的话,为了不同的东西而放弃它)。

I've been working with node.js for a while on a chat app (I know, very original, but I figured it'd be a good learning project). Underscore.js provides a lot of functional programming concepts which look interesting, so I'd like to understand how a functional program in JavaScript would be setup.

From my understanding of functional programming (which may be wrong), the whole idea is to avoid side effects, which are basically having a function which updates another variable outside of the function so something like

var external;
function foo() {
   external = 'bar';
}
foo();

would be creating a side effect, correct? So as a general rule, you want to avoid disturbing variables in the global scope.

Ok, so how does that work when you're dealing with objects and what not? For example, a lot of times, I'll have a constructor and an init method that initializes the object, like so:

var Foo = function(initVars) {
   this.init(initVars);
}

Foo.prototype.init = function(initVars) {
   this.bar1 = initVars['bar1'];
   this.bar2 = initVars['bar2'];
   //....
}

var myFoo = new Foo({'bar1': '1', 'bar2': '2'});

So my init method is intentionally causing side effects, but what would be a functional way to handle the same sort of situation?

Also, if anyone could point me to either a Python or JavaScript source code of a program that tries to be as functional as possible, that would also be much appreciated. I feel like I'm close to "getting it", but I'm just not quite there. Mainly I'm interested in how functional programming works with traditional OOP classes concept (or does away with it for something different if that's the case).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

只怪假的太真实 2024-09-05 18:14:26

您应该阅读这个问题:

Javascript 作为函数式语言

有很多有用的链接,包括:

现在,谈谈我的看法。很多人误解了 JavaScript,可能是因为它的语法看起来像大多数其他编程语言(其中 Lisp/ Haskell/OCaml 看起来完全不同)。 JavaScript不是面向对象的,它实际上是一种基于原型的语言< /a>.它没有类或经典继承,因此不应该与 Java 或 C++ 进行比较。

JavaScript 比 Lisp 更好;它有闭包和一流的功能。使用它们,您可以创建其他函数式编程技术,例如 部分应用(柯里化)。

让我们举个例子(使用node.js中的sys.puts):

var external;
function foo() {
    external = Math.random() * 1000;
}
foo();

sys.puts(external);

为了消除全局副作用,我们可以将它包装在一个闭包中:

(function() {
    var external;
    function foo() {
        external = Math.random() * 1000;
    }
    foo();

    sys.puts(external);
})();

注意,我们实际上不能用external 或 foo 超出范围。他们完全封闭在自己的封闭之中,无法触碰。

现在,要消除外部副作用:

(function() {
    function foo() {
        return Math.random() * 1000;
    }

    sys.puts(foo());
})();

最后,该示例不是纯功能性的,因为它不可能。使用随机数从全局状态读取(以获得种子)并打印到控制台是一个副作用。

我还想指出,将函数式编程与对象混合在一起是完全可以的。以此为例:

var Square = function(x, y, w, h) {
   this.x = x;
   this.y = y;
   this.w = w;
   this.h = h;
};

function getArea(square) {
    return square.w * square.h;
}

function sum(values) {
    var total = 0;

    values.forEach(function(value) {
        total += value;
    });

    return total;
}

sys.puts(sum([new Square(0, 0, 10, 10), new Square(5, 2, 30, 50), new Square(100, 40, 20, 19)].map(function(square) {
    return getArea(square);
})));

正如您所看到的,在函数式语言中使用对象就可以了。有些 Lisp 甚至有称为属性列表的东西,可以将其视为对象。

以函数式风格使用对象的真正技巧是确保您不依赖它们的副作用,而是将它们视为不可变的。一种简单的方法是,每当您想要更改属性时,只需创建一个包含新详细信息的对象并传递该对象(这是 Clojure 和 Haskell 中经常使用的方法)。

我坚信函数方面在 JavaScript 中非常有用,但最终,您应该使用任何使代码更具可读性并且适合您的东西。

You should read this question:

Javascript as a functional language

There are lots of useful links, including:

Now, for my opinion. A lot of people misunderstand JavaScript, possibly because its syntax looks like most other programming languages (where Lisp/Haskell/OCaml look completely different). JavaScript is not object-oriented, it is actually a prototype-based language. It doesn't have classes or classical inheritance so shouldn't really be compared to Java or C++.

JavaScript can be better compared to a Lisp; it has closures and first-class functions. Using them you can create other functional programming techniques, such as partial application (currying).

Let's take an example (using sys.puts from node.js):

var external;
function foo() {
    external = Math.random() * 1000;
}
foo();

sys.puts(external);

To get rid of global side effects, we can wrap it in a closure:

(function() {
    var external;
    function foo() {
        external = Math.random() * 1000;
    }
    foo();

    sys.puts(external);
})();

Notice that we can't actually do anything with external or foo outside of the scope. They're completely wrapped up in their own closure, untouchable.

Now, to get rid of the external side-effect:

(function() {
    function foo() {
        return Math.random() * 1000;
    }

    sys.puts(foo());
})();

In the end, the example is not purely-functional because it can't be. Using a random number reads from the global state (to get a seed) and printing to the console is a side-effect.

I also want to point out that mixing functional programming with objects is perfectly fine. Take this for example:

var Square = function(x, y, w, h) {
   this.x = x;
   this.y = y;
   this.w = w;
   this.h = h;
};

function getArea(square) {
    return square.w * square.h;
}

function sum(values) {
    var total = 0;

    values.forEach(function(value) {
        total += value;
    });

    return total;
}

sys.puts(sum([new Square(0, 0, 10, 10), new Square(5, 2, 30, 50), new Square(100, 40, 20, 19)].map(function(square) {
    return getArea(square);
})));

As you can see, using objects in a functional language can be just fine. Some Lisps even have things called property lists which can be thought of as objects.

The real trick to using objects in a functional style is to make sure that you don't rely on their side effects but instead treat them as immutable. An easy way is whenever you want to change a property, just create a new object with the new details and pass that one along, instead (this is the approach often used in Clojure and Haskell).

I strongly believe that functional aspects can be very useful in JavaScript but ultimately, you should use whatever makes the code more readable and what works for you.

姜生凉生 2024-09-05 18:14:26

您必须了解函数式编程和面向对象编程在某种程度上是相互对立的。不可能同时是纯函数和纯面向对象。

函数式编程都是关于无状态计算的。 面向对象编程都是关于状态转换的。 (paraphasing this。希望不会太糟糕)

JavaScript 更对象化面向而非功能。这意味着如果您想以纯函数式风格进行编程,则必须放弃该语言的大部分内容。特别是所有面向对象的部分。

如果您愿意更加务实,您可以使用来自纯函数世界的一些灵感。

我尝试遵守以下规则:

执行计算的函数不应改变状态。并且改变状态的函数不应该执行计算。此外,改变状态的函数应该改变尽可能少的状态。目标是拥有许多只做一件事的小功能。然后,如果您需要做任何大事,您可以编写一堆小函数来完成您需要的事情。

遵循这些规则可以获得许多好处:

  1. 易于重用。函数越长、越复杂,它也就越专业,因此它被重用的可能性就越小。相反的含义是较短的函数往往更通用,因此更容易重用。

  2. 代码的可靠性。如果代码不太复杂,就更容易推断出代码的正确性。

  3. 当函数只做一件事时,测试函数会更容易。这样就可以减少需要测试的特殊情况。

更新:

合并了评论中的建议。

更新2:

添加了一些有用的链接。

You have to understand that functional programming and object oriented programming are somewhat antithetical to each other. It's not possible to both be purely functional and purely object oriented.

Functional programming is all about stateless computations. Object oriented programming is all about state transitions. (Paraphasing this. Hopefully not too badly)

JavaScript is more object oriented than it is functional. Which means that if you want to program in a purely functional style, you have to forego large parts of the language. Specifically all the object orient parts.

If you are willing to be more pragmatic about it, there are some inspirations from the purely functional world that you could use.

I try to adhere to the following rules:

Functions that perform computations should not alter state. And functions that alter state should not perform computations. Also, functions that alter state should alter as little state as possible. The goal is to have lots of little functions that only do one thing. Then, if you need to do anything big, you compose a bunch of little functions to do what you need.

There are a number of benefits to be gained from following these rules:

  1. Ease of reuse. The longer and more complex a function is, the more specialized it also is, and therefore the less likely it is that it can be reused. The reverse implication is that shorter functions tend to more generic and therefore easier to reuse.

  2. Reliability of code. It is easier to reason about correctness of the code if it is less complex.

  3. It is easier to test functions when they do only one thing. That way there are fewer special cases to test.

Update:

Incorporated suggestion from comment.

Update 2:

Added some useful links.

素手挽清风 2024-09-05 18:14:26

我认为, http://documentcloud.github.com/underscore/ 应该很适合你需要的 - 它为函数式编程提供了最重要的高阶函数,并且没有用于 DOM 操作的客户端函数,而服务器端不需要这些函数。虽然我没有这方面的经验。

附带说明:恕我直言,函数式编程的主要特征是函数的引用透明度 - 函数结果仅取决于其参数 - 函数不依赖于其他对象的更改,并且除了其结果值之外不会引入任何更改。它可以轻松推断程序的正确性,并且对于实现可预测的多线程(如果相关)非常有价值。尽管 JavaScript 不是 FP 的首选语言 - 我预计不可变数据结构的使用性能会非常昂贵。

I think, http://documentcloud.github.com/underscore/ should be nice fit for what you need - it provides the most important higher-order functions for functional programming and does not has client-side functions for DOM manipulation which you don't need for server side. Though I don't have experience with it.

As a side note: IMHO primary feature of functional programming is Referential transparency of a function - function result depends only on its parameters - function does not depend on changes on other objects and does not introduce any change except its result value. It makes it easy to reason about program's correctness and very valuable for implementing of predictable multi-threading (if relevant). Though JavaScript is not the bet language for FP - I expect immutable data structures to be very expensive performance-wise to use.

回首观望 2024-09-05 18:14:26

所以有两件事需要指出,

  1. 在你的第一个例子中,你的变量不会泄漏到全局区域,并且应该这样做,尽量不要在没有声明变量的情况下使用变量,即 test = 'data' 会导致数据泄漏到全局区域。

  2. 你的第二个例子也是正确的,bar1和bar2只会在Foo对象上声明。

要记住的事情尽量不要过度使用原型,因为它适用于您创建的每个对象,这可能会占用大量内存,具体取决于对象的复杂程度。

如果您正在寻找应用程序开发框架,请查看 ExtJs。我个人认为它非常适合您尝试开发的模型。在投入大量资金之前,请记住他们的许可模式是如何运作的。

So 2 things to point out ,

  1. In your first example your variable would not be leaking into the global area and is the way it should be done , try to never use variables without declaring them i.e. test = 'data' would cause data to leak into the global area.

  2. Your second example is correct as well , bar1 and bar2 would only be declared on the Foo object.

Things to keep in mind try not to overuse prototyping since it applies to every object that you create , this could be extremely memory intensive depending on how complex your objects are.

If you are looking for a app development framework , have a look at ExtJs. Personally I think it would fit perfectly into the model you are trying to develop against. Just keep in mind how their licensing model works before getting heavily invested in it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文