功能编程和DOM操作

prz*_*ekk 7 javascript dom functional-programming ecmascript-6

在以"功能"方式编写的脚本中,如何以最"纯粹"的方式操作DOM.

例如,如果我只需要更改元素宽度,我应该使用典型语法,如:

document.querySelector(".class").style.width = ...
Run Code Online (Sandbox Code Playgroud)

或写专用功能,如:

function resize(el, w) {
    return el.style.width = w;
}

resize(document.querySelector(".class", 100));
Run Code Online (Sandbox Code Playgroud)

我想,我理解函数式编程的一般概念,但我遇到的所有例子都集中在操作数字或字符串上.操纵DOM被认为是副作用,所以我想知道如何以正确的方式做到这一点.

编辑:

下面更新了代码,问题是,是iit functionall?如果不是,我会感激建议如何重写它.

"use strict";

const outerW = num => 100 * num + "%";
const innerW = num => 100 / num + "%";
const setW = (el, w) => el.style.width = w;

const mask = document.querySelector(".slider__slides__mask");
const slides = document.querySelectorAll(".slider__slide");

setW(mask, outerW(slides.length));
slides.forEach(function(item) {
    setW(item, innerW(slides.length));
});
Run Code Online (Sandbox Code Playgroud)

小智 16

无论是功能性的还是命令式的,每个有意义的程序最终都必须产生一些效果.函数式编程的想法是将这些效果转移到程序的边缘,这样很大一部分仍然是纯粹的.这使得理由更容易.

但是如何将其付诸实践呢?

使功能可组合

Javascript函数通常被定义为多参数函数.因此,我们不能在呼叫方推迟他们的评估:

// pure

const add = (x, y) => x + y;

const log = x => console.log(x);

// impure

log(add(2, 3));
Run Code Online (Sandbox Code Playgroud)

命令式风格也是如此:

let x = 2, y = 3;

// impure

console.log(x + y);
Run Code Online (Sandbox Code Playgroud)

结果是pure calculate(add)不能与effect(log)分开.这对于这个草图来说并不是什么大问题,但是一旦你的程序变得越来越大,这些分散的效果就会影响它的可读性和可理解性.

为防止此行为,函数必须变为可组合,即它们的最后一个参数必须部分适用:

// pure

const comp = (f, g) => x => f(g(x));

const add = x => y => x + y;

const log = x => console.log(x);

const addAndLog = comp(log, add(2));

// impure

addAndLog(3);
Run Code Online (Sandbox Code Playgroud)

你可能要考虑柯里以获取更多信息.

用thunk包裹效果

使用thunk,我们可以将效果进一步移动到边缘.thunk只是一个不需要参数的函数,因此代表了一个延迟计算:

// pure

const comp = (f, g) => x => f(g(x));

const add = x => y => x + y;

const log = x => () => console.log(x);

const addAndLog = comp(log, add(2));

const eventuallyLog = addAndLog(3); // still pure

// impure (release the effect)

eventuallyLog(); // invoke the thunk
Run Code Online (Sandbox Code Playgroud)

您可能需要查看IO monad以获取更多信息.

一个(几乎)现实世界的例子

// pure

const on = (type, element) => f => {
  element.addEventListener(type, f, true);
  return () => element.removeEventListener(type, f, true);
}

const compose = (...fs) => x => fs.reduce((acc, f) => f(acc), x);

const countFrom = x => () => (x++, x);

const log = x => console.log(x);

const filter = pred => f => x => pred(x) ? f(x) : x;

const even = x => x % 2 === 0;

const concat = y => x => x + y;

const filterEven = filter(even);

const clickStream = on("click", document);

const computation =
 compose(countFrom(0), filterEven(compose(concat("!"), log)));

// impure (release the effects)

console.log("click on the section above");

clickStream(computation);
Run Code Online (Sandbox Code Playgroud)

副作用(双关语)add读起来像普通英语.我最近被告知这不是一个理想的财产.好吧,我不同意.