2016-09-28 2 views
5

Je mettais en œuvre un algorithme GCD simple dans ES6 (via node-esml) et suis arrivé (à moi) un comportement étrange avec la mise à jour des valeurs de variables dans une boucle while. Ce code fonctionne fantastiquement:L'affectation de la déstructuration dans la boucle while de la fonction ES6 ne se produit pas en boucle?

function gcdWithTemp(x, y) { 
    let [r, rdash] = [x, y] 
    while (r != 0) { 
    q = Math.floor(rdash/r) 
    temp = r 
    r = rdash - q * r 
    rdash = temp 
    } 
    return(rdash) 
} 
console.log(gcdWithTemp(97, 34)) 

Renvoyer la réponse attendue de 1. Cependant, si je retire la variable temporaire et utilisez plutôt l'affectation déstructurant pour essayer d'atteindre les mêmes résultats:

function gcdWithDestructuredAssignment(x, y) { 
    let [r, rdash] = [x, y] 
    while (r != 0) { 
    q = Math.floor(rdash/r) 
    [r, rdash] = [rdash - q * r, r] 
    } 
    return(rdash) 
} 
console.log(gcdWithDestructuredAssignment(97, 34)) 

Il ne se termine jamais, plus débogage montre que r aura toujours la première valeur attribuée à, x. Il semble que ces deux implémentations devraient être identiques? J'ai également essayé avec var au lieu de let en vain. Suis-je en train de mal comprendre le point de la déstructuration ou de manquer quelque chose de subtil? Ou est-ce un bug?

+1

Vos variables 'q' et' temp' sont [implicitement globales] (http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html). Utilisez le mode strict! – Bergi

+1

Btw, pourquoi ne pas simplement écrire 'la fonction gcd (r, rdash) {' et omettre le 'let [r, rdash] = [x, y]'? – Bergi

Répondre

7

C'est un problème non pas avec une affectation destructuring, mais avec ASI (insertion automatique de point-virgule). Ces deux lignes:

q = Math.floor(rdash/r) 
[r, rdash] = [rdash - q * r, r] 

dans la pratique signifie ceci:

q = Math.floor(rdash/r)[r, rdash] = [rdash - q * r, r] 

ce qui est évidemment pas ce que vous vouliez dire. Pour corriger cela, ajoutez un point-virgule devant [:

function gcdWithDestructuredAssignment(x, y) { 
 
    let [r, rdash] = [x, y] 
 
    while (r != 0) { 
 
    q = Math.floor(rdash/r) 
 
    ;[r, rdash] = [rdash - q * r, r] 
 
    } 
 
    return(rdash) 
 
} 
 
console.log(gcdWithDestructuredAssignment(97, 34))

Bien sûr, vous pouvez ajouter le point-virgule manquant à la fin de la ligne précédente à la place (q = Math.floor(rdash/r);), mais puisque vous don en général n'utilisez pas de point-virgule, je suppose que vous utilisez npm coding style.

+1

Félicitations pour avoir trouvé le point-virgule manquant, mais pourquoi l'ajouteriez-vous au début de la deuxième ligne plutôt qu'à la fin de la première comme d'habitude? – Aaron

+2

@Aaron C'est [style de codage npm] (https://docs.npmjs.com/misc/coding-style#semicolons). –

+0

Merci, heureux d'apprendre cela. Il est en effet logique de mettre le point-virgule au début des lignes problématiques si elles sont généralement omises et le problème est l'agrégation avec la ligne précédente, quelle qu'elle soit. – Aaron