javascript编程题

    科技2026-08-23  5

    javascript编程题

    A lot of JavaScript programmers seem to think that functional programming is simply writing bare functions without classes. But that’s procedural programming, not functional programming. So what is functional programming then?

    许多JavaScript程序员似乎认为函数式编程只是在编写没有类的裸函数。 但这是过程编程,而不是功能编程。 那么什么是函数式编程呢?

    什么是函数式编程? (What is functional programming?)

    Ask a math professor what factorial is, and he is likely to come up with a definition similar to this definition from a Math textbook:

    询问数学教授什么是阶乘,他可能会从数学教科书中得出类似于该定义的定义:

    It turns out this is very similar to how you implement factorial in Haskell, and that’s not a coincidence:

    事实证明,这与您在Haskell中实现阶乘非常相似,这不是巧合:

    factorial 0 = 1 factorial n = n * factorial (n - 1)

    In functional programming, you define what things are — like your math professor would — as opposed to writing step-by-step instructions on how to calculate things. The latter is imperative programming.

    在函数式编程中,您像数学教授一样定义了事物,而不是编写关于如何计算事物的分步说明。 后者是命令式编程。

    Here’s how a JavaScript programmer might implement factorial:

    JavaScript程序员可以通过以下方式实现阶乘:

    function factorial(n) { let x = 1; while (n > 0) { x = x * n; n = n — 1; } return x;}

    This is a function but it is not functional because it mutates state and uses iteration.

    这是一个函数,但不起作用,因为它会突变状态并使用迭代。

    功能方式 (The functional way)

    To be functional it is not sufficient to simply remove classes and write top-level functions. You have to completely change your way of thinking. The functional way has no side effects or state mutations. It has no assignments, no iteration, and no conditional statements.

    要实现功能,仅删除类并编写顶级功能是不够的。 您必须完全改变思维方式。 功能方式没有副作用或状态突变。 它没有赋值,没有迭代,也没有条件语句。

    Assignment and iteration are typical of imperative programming. In functional programming changing the value of a variable using an assignment statement is not allowed. Recursion takes the place of iteration, and conditional expressions are favored over conditional statements.

    赋值和迭代是命令式编程的典型特征。 在函数式编程中,不允许使用赋值语句更改变量的值。 递归代替了迭代,条件表达式比条件语句更受青睐。

    JavaScript的局限性 (Limitations of JavaScript)

    Limitations of JavaScript become obvious when you try to follow the rules of functional programming in JavaScript.

    当您尝试遵循JavaScript中的函数式编程规则时,JavaScript的局限性显而易见。

    First, let’s rewrite the factorial function above using recursion. After all, JavaScript supports recursion too, right?

    首先,让我们使用递归重写上面的阶乘函数。 毕竟,JavaScript也支持递归,对吗?

    function factorial(n, product = 1) { if (n < 2) { return product; } return factorial(n - 1, n * product);}

    Unfortunately, this doesn’t work very well in JavaScript because it lacks a critical feature known as tail call optimization (TCO). This feature prevents the stack from growing in proportion to the number of levels of recursion. Chrome has decided not to implement this feature. Lack of TCO means you can’t avoid iteration in JavaScript.

    不幸的是,这在JavaScript中不能很好地工作,因为它缺少称为尾部调用优化( TCO )的关键功能。 此功能可防止堆栈与递归级别的数量成比例地增长。 Chrome已决定不实施此功能。 缺少TCO意味着您无法避免JavaScript的迭代。

    But that’s not all. Let’s look at some features that make functional programming awesome.

    但这还不是全部。 让我们看一些使函数式编程很棒的功能。

    Here’s how you calculate the sum of the first 10 prime numbers using Rust programming language (assumes existence of is_prime function):

    这是使用Rust编程语言计算前10个质数之和的方法(假设存在is_prime函数):

    let sum = (0..).into_iter().filter(|&x| is_prime(x)).take(10).sum();

    You can do something that looks similar (if a bit longer) in JavaScript too:

    你可以在JavaScript中的东西,看起来类似(如果时间长一点)太:

    const sum = [...Array(100)].map((_, i) => i).filter(n => is_prime(n)).slice(0, 10).reduce((a, b) => a + b, 0);

    Unfortunately, it only looks similar. Appearances can be deceptive. It doesn’t work similar at all. This is because JavaScript lacks a critical feature known as lazy evaluation. Lazy evaluation means not calculating things until they are actually needed.

    不幸的是,它看起来很相似。 外观可能具有欺骗性。 它不会在所有的工作类似。 这是因为JavaScript缺乏称为惰性评估的关键功能。 懒惰的评估意味着直到实际需要时才进行计算。

    In the JavaScript version, an array of 100 elements is created whether you use all 100 elements or not. In the Rust version an infinite range (0..) is specified but thanks to lazy evaluation it doesn’t actually try to create an infinite range because you are not using all of those values. In the Rust version calculations are only done when the final consumer of the iteration actually tries to use the result of the calculation.

    在JavaScript版本中,无论是否使用全部100个元素,都会创建一个包含100个元素的数组。 在Rust版本中,指定了一个无限范围(0 ..),但是由于采用了惰性计算,因此实际上并没有尝试创建一个无限范围,因为您没有使用所有这些值。 在Rust版本中,仅当迭代的最终使用者实际尝试使用计算结果时才进行计算。

    Because of lack of lazy evaluation in JavaScript, code that looks cool — like in functional languages — is actually quite inefficient when compared to functional languages.

    由于JavaScript中缺乏惰性评估,因此看起来像功能语言一样酷的代码与功能语言相比实际上效率很低。

    There are even more cool functional features missing in JavaScript, such as pattern matching.

    JavaScript中甚至还缺少一些很酷的功能,例如模式匹配。

    Because of a lack of features such as tail call optimization and lazy evaluation you can’t do “real” functional programming in JavaScript.

    由于缺少诸如尾部调用优化和延迟评估之类的功能,因此您无法在JavaScript中进行“真正的”功能编程。

    功能编程和副作用 (Functional programming and side effects)

    In functional programming, a function is supposed to not have any side effects. It is not supposed to modify any global state, it is not supposed to print anything to the console and it is certainly not supposed to mutate the DOM.

    在函数式编程中,函数应该没有任何副作用。 它不应该修改任何全局状态,不应该在控制台上打印任何内容,当然也不应该对DOM进行更改。

    If a function can’t change anything in the world, and your program is built of such functions, then how is it supposed to do anything useful? At some point you’re going to need side-effects such as mutating the DOM, right?

    如果一个函数不能改变世界,而您的程序是由此类函数构建的,那么它应该怎么做呢? 在某些时候,您将需要副作用,例如使DOM变异,对吗?

    It turns out that FP languages such as Haskell have a system for dealing with functions that have side-effects, that neatly separates the part of the program that is pure and the part of the program that is impure (and does all the dirty work like updating the screen). Impure parts of the program is fenced off from the pure parts. Pure functions cannot call impure functions.

    事实证明,诸如Haskell之类的FP语言具有一个用于处理具有副作用的函数的系统,该系统将纯净的程序部分与纯净的程序部分巧妙地分开(并完成了所有肮脏的工作,例如更新屏幕)。 程序的不纯部分与纯部分无关。 纯函数不能调用不纯函数。

    With pure and impure parts separated, we can still reason about our mostly pure program (which is the majority of our code) and take advantage of all the things that purity offers while still communicating with the outside world.

    将纯净的部分和不纯净的部分分离开来,我们仍然可以对我们大多数纯净的程序(这是我们的大部分代码)进行推理,并在与外界进行交流的同时利用纯净度提供的所有功能。

    The important part here is keeping portions of your code that has side-effects separate — and minimizing the amount of such code. If code that has side-effects is spread all over your program then you are not really using functional style.

    这里的重要部分是将具有副作用的代码部分分开,并最大程度地减少此类代码的数量。 如果具有副作用的代码遍布整个程序,那么您实际上并没有使用函数式样式。

    何时使用函数式编程 (When to use functional programming)

    Just because you can’t do pure functional programming in JavaScript doesn’t mean you shouldn’t write functional-style code where it makes sense. If you are a JavaScript programmer, whether you realize it or not, you may already be using features that originally came from functional programming languages, such as lambdas and closures.

    仅仅因为您不能用JavaScript进行纯函数式编程并不意味着您不应该在有意义的地方编写函数式代码。 如果您是JavaScript程序员,则无论您是否意识到,您可能已经在使用最初来自函数式编程语言的功能,例如lambda和闭包。

    Modern programming languages such as Rust are multi-paradigm for a reason. There is no reason to eschew one paradigm in favor of another. Among some JavaScript programmers, it has become fashionable to completely avoid classes and OOP because they think functional is better. But given that you can’t do real functional programming in JavaScript, completely avoiding OOP will only eliminate the advantages of OOP while not gaining the benefits of pure functional style.

    由于某种原因,诸如Rust之类的现代编程语言是多种范例。 没有理由避开一个范例,而转向另一个范例。 在一些JavaScript程序员中,完全避免使用类和OOP已成为一种时尚,因为他们认为功能更好。 但是,鉴于您无法使用JavaScript进行真正的函数式编程,完全避免OOP只会消除OOP的优势,而不会获得纯函数式风格的优势。

    功能编程的沉睡和唤醒 (The slumber and awakening of functional programming)

    Functional programming is not new. It is almost as old as programming itself. The first functional programming language, LISP, was developed in the late 1950s. Functional programming has been available for many decades but it didn’t garner much interest from the mainstream until recently. It is important to understand the reason for its resurgence before abandoning all other paradigms in favor of functional.

    函数式编程并不新鲜。 它几乎和编程本身一样古老。 第一种函数式编程语言LISP于1950年代后期开发。 函数式编程已经存在了数十年,但是直到最近才引起主流的兴趣。 重要的是在放弃所有其他范例以支持功能之前,了解其重新流行的原因。

    Moore’s law is coming to an end, and CPUs are adding more cores instead of making cores faster and faster as they have done in the past. Taking advantage of multiple cores is hard.

    摩尔定律即将终结,CPU正在增加更多的内核,而不是像过去那样使内核越来越快。 利用多核很难。

    To take advantage of the extra cores in a CPU you add threads, but if these threads are continually needing to lock in order to serialize access to shared state then concurrency is diminished. The more cores you have, the more threads you have, and the more the contention for access to shared state.

    要利用CPU中额外的内核,您可以添加线程,但是如果这些线程持续需要锁定以便序列化对共享状态的访问,则会减少并发性。 您拥有的核心越多,拥有的线程越多,访问共享状态的争用就越多。

    What if you used a different style of programming that doesn’t use shared state? Then you wouldn’t have to lock so much. The actor model is one such style and functional programming, because it eschews mutable state, is another. This makes it easier to take advantage of multicore processors and that is the reason for the renewed interest in functional programming.

    如果您使用了不使用共享状态的另一种编程风格,该怎么办? 然后,您不必锁定太多。 actor模型就是这样一种样式和功能编程,因为它避开了可变状态,是另一种。 这使得利用多核处理器变得更加容易,这就是对功能编程重新产生兴趣的原因。

    But when it comes to JavaScript these benefits don’t exist because JavaScript code doesn’t use multiple threads (except for web workers, but web workers don’t share mutable state with the main thread). That’s not to say there are no benefits at all to incorporating some functional style into JavaScript code, but wholesale replacement of OOP with functional style is not warranted.

    但是,当涉及JavaScript时,这些好处并不存在,因为JavaScript代码不使用多个线程(Web工作者除外,但Web工作者不与主线程共享可变状态)。 这并不是说将某些功能样式集成到JavaScript代码中根本没有任何好处,但是不保证将OOP完全替换为功能样式。

    翻译自: https://medium.com/@petilon404/dysfunctional-programming-in-javascript-cae5c085a76e

    javascript编程题

    Processed: 0.012, SQL: 9