2017-01-27 1 views
0

Ce problème se produit dans les nœuds 6.9.4 et 7.0.0, et je n'arrive pas à comprendre pourquoi. Je n'ai pas testé dans d'autres versions. Voir les commentaires dans le programme Node.js ci-dessous:Pourquoi cette discordance dans la portée lexicale se produit-elle?

const express = require('express'); 
const adaro = require('adaro'); 

const app = express(); 

const tabs = require('./config/tabs.json'); 
const config = require('./config/locals.js'); 

function getLocals(name) { 
    const modifiedTabs = config.tabs.map(tab => { 
    return Object.assign(tab, {active: tab.name === name}); 
    }); 

    return Object.assign({tab: name}, config, {tabs: modifiedTabs}); 
} 

app.engine('dust', adaro.dust()); 
app.set('view engine', 'dust'); 
app.set('x-powered-by', false); 

app.use(express.static('static')); 

tabs.map(tab => tab.name).forEach(name => { 
    const locals = getLocals(name); 
    const tab = locals.tabs.find(tab => tab.active); 

    // these are always true 
    console.log(tab === locals.tabs.find(tab => tab.active)); 

    function callback(req, res) { 
    // const locals = getLocals(name); 
    // this should be true, but is false unless the line above is commented in 
    console.log(tab === locals.tabs.find(tab => tab.active)); 
    res.render('main', locals); 
    } 

    if (tab.url !== '/' + tab.id) { 
    app.get(tab.url, callback); 
    } 

    app.get('/' + tab.id, callback); 
}); 

app.all('*', function (req, res) { 
    res.sendStatus(404); 
}); 

app.listen(process.env.PORT || 8000); 

Quelqu'un peut-il expliquer pourquoi cela se passe et comment y remédier?

+1

Déconnexion '' locals' et getLocals (nom) 'à la ligne que vous avez commenté. Ma conjecture est qu'ils seront différents parce que vous êtes en train de muter un objet quelque part sans le réaliser. – cdhowie

+0

* facepalm * Je viens de trouver la mutation: 'Object.assign (tab, {active: tab.name === name})' ligne 11 ... –

Répondre

0

J'ai trouvé le problème. En getLocals(), j'exécution

const modifiedTabs = config.tabs.map(tab => { 
    return Object.assign(tab, {active: tab.name === name}); 
}); 

Le Object.assign(tab, ...) l'objet tab écrase existant chaque fois qu'il est appelé, ne laissant que les dernières affectations à chaque onglet. Ainsi, toutes les vues affichent le dernier onglet du tableau comme actif, puisque toutes leurs propriétés active ont été remplacées par celles de la dernière configuration de l'onglet.

La solution a été de passer les arguments à Object.assign() afin que l'objet retourné a été créé plutôt que écrasé:

return Object.assign({active: tab.name === name}, tab);