2015-03-01 1 views
5

Ceci est une question plutôt générale. La programmation de type fonctionnel promeut l'idée qu'un programme consiste à transformer des données par des fonctions, et que la mutation doit être évitée (sauf peut-être dans une fonction, considérée comme une unité fondamentale d'abstraction).JavaScript de style fonctionnel: une bonne pratique pour éviter la mutation des arguments?

Mais dans ce programme:

function foo (bar) { 
    bar.k1 = "bananas"; 
    return bar; 
} 

var o = { k1: "apples", k2: "oranges"}; 
var p = foo(o); 

la variable externe o a subi une mutation au sein de foo parce bar est une référence à o, et, à la fin, o === p (ils font référence au même objet). Mais le paradigme fonctionnel s'attendrait plutôt à ce que p soit de nouvelles données.

La solution évidente est de cloner l'argument (e g en utilisant underscore/lodash de _.clone..):

function foo (_bar) { 
    var bar = _.clone(_bar); 
    bar.k1 = "bananas"; 
    return bar; 
} 

Mais je me demande si cela est la bonne façon de penser à ce problème. Dans une perspective FP, considéreriez-vous comme une bonne pratique de cloner les objets passés en arguments s'ils sont mutés? (Je suis conscient que tous les objets ne peuvent pas être clonés facilement, voire pas du tout, mais gardons les cas simples). Tes pensées?

+0

Mon 2 cents est d'écrire du code qui fonctionne avec la langue et ne pas s'accrocher aux techniques de programmation. La programmation fonctionnelle est bonne et dandy, mais si vous n'avez pas besoin d'un nouvel objet, il n'y a aucune raison d'en retourner un, quand vous pouvez simplement changer l'original. – adeneo

+0

Je dois retourner l'objet si je veux faire quelque chose comme: 'someOtherFunction (foo (o))'. Ce que vous voulez probablement dire, c'est que cela n'a pas d'importance s'il s'agit d'un nouvel objet ou d'une référence à l'objet externe. –

+0

Que ce soit important ou non dépend de vous? Avez-vous besoin de l'objet original inchangé, sinon il n'y a aucune raison d'en créer un nouveau, il suffit de retourner celui qui est passé à la fonction après sa modification. – adeneo

Répondre

5

Idéalement, la fonction doit renvoyer un nouvel objet chaque fois qu'il est appelé. Évidemment, pour des raisons de performances, ce n'est pas génial, c'est pourquoi il existe persistent data structures. Il y a quelques bibliothèques pour JS; immutable-js est sans doute le plus populaire.

Sinon, la mutation de l'objet est correcte, et dans JS c'est une pratique courante, car tous les projets ne bénéficieraient pas immédiatement des structures de données persistantes, plus le poids de la bibliothèque.

Notez également qu'en JavaScript, tout est passé par valeur, mais les valeurs elles-mêmes peuvent contenir des références.