Search code examples
javascriptnode.jsexpresslocals

Express.js - Setting res.locals changes the req object


I am very confused what is about happening here. I am trying to set a res.locals default profile picture for a user if they do not currently have one. Here is my code:

// Make user object available in templates.
app.use(function(req, res, next) {
  res.locals.user = req.user;
  if (req.user && req.user.profile) {
    console.log('Request Picture: ', req.user.profile);
    res.locals.user.profile.picture = req.user.profile.picture || defaults.imgs.profile;
    console.log('Request Picture After Locals: ', req.user.profile);
  }
  next();
});

// Console Results
Request Picture:  { picture: '',
  website: '',
  location: '',
  gender: '',
  name: 'picture' }
Request Picture After Locals:  { picture: '/img/profile-placeholder.png',
  website: '',
  location: '',
  gender: '',
  name: 'picture' }

I want to be able to write JADE without having to handle something like this: img(src=user.profile.picture || defaults.profile.picture). So the above code works fine in all of the JADE views.

But, I need to check the req.user.profile.picture somewhere else in order to change the picture.

if (!req.user.profile.picture) {do stuff}

As you can see above the req has been changed. Setting res.locals should not change the req object...correct!? Or am I missing something?

Thanks for any help!


Solution

  • Objects in Javascript are assigned by pointer. So, when you do this:

    res.locals.user = req.user;
    

    You now have both res.locals.user and req.user pointing at exactly the same object. If you then modify that object through either one, both are pointing at the same object so both will see the change.

    Perhaps what you want to do is to COPY the req.user object over to res.locals.user so you have two completely separate objects that can be modified independently.

    There are various mechanisms for copying (or cloning) an object in node.js shown here:

    Cloning an Object in Node.js

    There is also Object.assign()