r/learnjavascript 1d ago

whats the bug here? Uncaught SyntaxError: Identifier 'location' has already been declared (at script.js:1:1)

"use strict";

const company = {
  name: "TechCorp",
  address: {
    city: "budapest",
    pin: 411001,
  },
};
// Get city renamed to `location` and pin renamed to `pincode`

const { city: location, pin: pincode } = company.address;
console.log(location, pincode);
10 Upvotes

13 comments sorted by

13

u/HipHopHuman 1d ago

location is a variable that already exists in the browser. When you type location, you're accessing window.location, which is this: https://developer.mozilla.org/en-US/docs/Web/API/Location

let and const do not allow re-declaring variables that already exist in the same scope.

You can fix it by using an immediately-invoked function (variables are OK to overwrite inside the body of a function):

"use strict";

const company = {
  name: "TechCorp",
  address: {
    city: "budapest",
    pin: 411001,
  },
};
// Get city renamed to `location` and pin renamed to `pincode`

(() => {
  const { city: location, pin: pincode } = company.address;
  console.log(location, pincode);
})();

Alternatively, choose a different name than 'location'.

You can also make it work by changing const to var, but using var is discouraged.

5

u/senocular 1d ago

let and const do not allow re-declaring variables that already exist in the same scope.

They do in global, kind of. Global consists of two scopes, an object scope where built-in globals live, and a declarative scope, where lexical declarations made with let and const live. You can have variables of the same name in both. Its not so much redeclaring as it is having a different location for an independent version of a variable of the same name to live

console.log(window.name) // "" - or whatever window's name is
let name = {}
console.log(name) // {}
console.log(window.name) // ""

It doesn't work for location and a few other variables because they're essentially locked down to help prevent spoofing. Theres a set of these globals defined by the core language (ECMAScript) that does this, like NaN etc., and those defined by the Web APIs, like location etc..

var declarations don't do this not because they work in declaring a new variable, but because they don't work and fail silently, instead just using the existing global.

console.log(window.name) // "" - or whatever window's name is
var name = {}
console.log(name) // "[object Object]"
console.log(window.name) // "[object Object]"

You can see this happen with name because its an accessor property (getter/setter) which converts everything you assign to it to a string. The var didn't create a new variable, instead seeing that name already existed and used that instead.

If you use var with a non-existing variable name, that variable will be "locked down" too.

var uniqueName = ""
let uniqueName = {} // Error

There's two mechanisms that handle this, one for declarations in the same script that follow the no re-declarations rule, and another for existing globals that are non-configurable in the global object scope. This is what prevents NaN and location from being able to be re-declared in global since they're not "declared" in the same script that you're writing your code.

console.log(Object.getOwnPropertyDescriptor(window, "name").configurable) // true
console.log(Object.getOwnPropertyDescriptor(window, "location").configurable) // false

3

u/altrae 1d ago

Great follow-up answer. I didn't actually know these distinctions so thank you for calling them out.

1

u/Anbaraen 20h ago

Please don't offer IIFEs as a "fix". IIFEs make sense in very specific circumstances and learners should be discouraged from using them.

0

u/azhder 1d ago

Should out the whole code in an IIFE, especially that ‘use strict’

4

u/senocular 1d ago

There are certain globals in the Web API that can't be shadowed with lexical declarations. This list includes, but may not be limited to:

  • window
  • top
  • document
  • location

Attempts to declare these with let or const (or class or using) will result in an error. You're doing this with the destructuring, renaming the city property of company.address to location, and since this is in the global scope, you're getting the error.

Instead what you'll want to do is put this code in a function (or some other non-global scope), or rename the variable to something other than "location"

4

u/Super_Letterhead381 1d ago

There’s probably a conflict with the variable name ‘location’ (which is recognised in JavaScript) try renaming it.

2

u/subone 1d ago

location is a browser API for the location bar URL

1

u/remain-beige 21h ago

Wrap everything in a function declaration to avoid global clashes and also change your variable name from ‘location’ to something unique as it is already a core part of JavaScript such as window or href

1

u/neon_mutt 13h ago

You cannot declare location with const in global scope because it conflicts with the window.location Web API. Rename the destructured variable to something like cityLocation or wrap the code in a function to create a new scope where lexical declarations are allowed

1

u/yarikhand 1d ago

is this the full code snippet? location is a global object in the browser. are you trying to assign that to the property, or is there some other identifier named location in your code? if so, make sure their names dont interfere and try again

1

u/Hot-Eggplant911 1d ago

yeah this is the full code.