具有对象的Javascript纯函数示例 [英] Javascript pure function example with objects

查看:117
本文介绍了具有对象的Javascript纯函数示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个不纯功能的例子。注意变量 a 超出了函数作用域的范围。为了解决这个问题,我们可以在函数内克隆对象并返回一个副本,但这是正确的方式吗?



有什么方法可以使函数 transformObject 纯?

  var a = {
a:1,
b:2
};

函数transformObject(obj){
var ref = obj;
_.each(ref,function(val,index){
ref [index] = val * 2;
});
return ref;

$ bs bs = JSON.stringify
$('#code')。text(s(transformObject(a)))
$('#code2') .text(s(a))

https://jsfiddle.net/br17kk2h/1/ 解决方案

一个纯函数遵循三个主要原则:

该函数有一个单一的职责



函数应该做只有一件事。



该函数没有副作用



该函数不改变其范围之外的状态。



该函数是引用透明的



该函数为相同的输入输出相同的值。



下一步是探讨这些原理在函数设计中的影响。

您的函数已经符合第一个原则,虽然名称应该改进;)

它也符合第二个原则,因为它不会修改其范围外的其他任何内容(它的输入参数)。



不幸的是,它不符合第三个原则:

  var a = {
a:1,
b:2
};

var b = transformObject(a); // b = {2,4}

var c = transformObject(a); // c = {4,8}

相同的输入( a ),但输出不同。这违反了第三条原则。

透明的函数需要不可变的数据。



Nina Scholz 已经发布了一个很好的答案:

 函数transformObject(a){
var b = {}; (b){b [k] = a [k] * 2;});
return b;
}

但它只能用,因为输入对象不包含任何嵌套的其他对象它现在有一些很好的库,可以为你提供不可变的结构(比如

一个使用ImmutableJS的简单示例:



<$ ($)$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' ;'
}

it('is immutable',()=> {

let state = List.of('Avengers','Antman') ;
let nextState = addMovie(state,'超人');

expect(nextState).to.equal(List.of(
'Avengers',
''Antman',
'超人'
));

expect(state).to.equal(List.of(
'Avengers',
'Antman'
));
});

('可以更新并返回另一个不可变列表',()=> {

let state = List.of(1,2,3,4) ;

let nextState = state.map(value => value * 2);

expect(nextState).to.equal(List.of(2,4, 6,8));
expect(state).to.equal(List.of(1,2,3,4));
});
});

您可以阅读更多关于不可变API的信息这里


I have the example below of an impure function. Note the variable a is outside of the function scope is being changed. To get around it, one could clone the object inside the function and return a copy, but is that the right way?

What are some options to make the function transformObject pure?

var a = {
    a : 1,
    b : 2
};

function transformObject(obj) {
    var ref = obj;
    _.each(ref, function(val, index){
        ref[index] = val*2;
    });
    return ref;
}

s=JSON.stringify
$('#code').text(s(transformObject(a)))
$('#code2').text(s(a))

https://jsfiddle.net/br17kk2h/1/

解决方案

A pure function follows three main principles:

The function has a single responsibility

The function should do only one thing.

The function has no side effects

The function does not change state outside its scope.

The function is referentially transparent

The function outputs the same value for the same inputs.

The next step is to explore the impact of these principles in the design of the function.

Your function already meets the first principle, although the name should be improved ;)

And it meets the second principle too, because it doesn't modify anything else outside its scope (its input parameters).

Unfortunately it doesn't meet the third principle:

var a = {
  a : 1,
  b : 2
};

var b = transformObject(a);//b = {2, 4}

var c = transformObject(a);//c = {4, 8}

Same inputs (a) but different outputs. That violates the third principle.

Referentially transparent functions needs immutable data.

A good answer has already been posted by Nina Scholz:

function transformObject(a) {
  var b = {};
  Object.keys(a).forEach(function (k) { b[k] = a[k] * 2; });
  return b;
}

But it only works because the input object does not contain any other object nested in it.

Right now there are some good libraries that gives you immutable structures (like ImmutableJS).

A simple example using ImmutableJS:

describe('a List', () => {

    function addMovie(currentState, movie) {
        return currentState.push(movie);
    }

    it('is immutable', () => {

        let state = List.of('Avengers', 'Antman');
        let nextState = addMovie(state, 'Superman');

        expect(nextState).to.equal(List.of(
            'Avengers',
            'Antman',
            'Superman'
        ));

        expect(state).to.equal(List.of(
            'Avengers',
            'Antman'
        ));
    });

    it('can be updated and returns another immutable List', () => {

        let state = List.of(1,2,3,4);

        let nextState = state.map(value => value*2);

        expect(nextState).to.equal(List.of(2,4,6,8));
        expect(state).to.equal(List.of(1,2,3,4));
    });
});

You can read more about immutable API here

这篇关于具有对象的Javascript纯函数示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆