Demystifying Array.@@unscopables: A Guide for JavaScript Developers


What is array.@@unscopables?

In JavaScript, array.@@unscopables (pronounced "array at double-at unscopables") is a special property on the Array.prototype object. It's a Symbol (a unique identifier) named Symbol.unscopables and holds an object that lists property names that are intentionally excluded from the with statement's environment binding.

Why is it used?

The with statement is a legacy feature in JavaScript that creates a new scope where variables from an object are directly accessible without the object prefix. However, it can lead to naming conflicts and unexpected behavior.

array.@@unscopables helps mitigate these issues by specifying properties that shouldn't be included in the with environment. This prevents accidental overwriting or unintended interactions with these properties.

Built-in Array.prototype[@@unscopables]

By default, the Array.prototype[@@unscopables] object is an empty object ({}), meaning no properties are excluded from the with environment for arrays. However, some browser implementations might have additional properties listed here for internal reasons.

Example (illustrative, not recommended)

const myArray = [1, 2, 3];

with (myArray) {
  console.log(length); // This would normally work (though using with is not recommended)
  // However, if array.@@unscopables included "length", this would throw a ReferenceError
}

Important points

  • array.@@unscopables is primarily for internal browser behavior and isn't typically used in everyday JavaScript development.
  • The with statement is generally discouraged due to potential scoping problems. It's better to use explicit object property access (myArray.length).
  • Avoid relying on with due to potential drawbacks.
  • The built-in Array.prototype[@@unscopables] is an empty object by default.
  • It's used to exclude properties from the with environment binding.
  • array.@@unscopables is a Symbol property on Array.prototype.


Customizing @@unscopables for an Object (not recommended for arrays)

This code shows how you could create a custom object and define @@unscopables to exclude specific properties from the with environment:

const myObject = {
  foo: 1,
  bar: 2,
  baz: 3,
  [Symbol.unscopables]: {
    bar: true, // Exclude "bar" from with binding
  },
};

with (myObject) {
  console.log(foo);   // Output: 1 (accessible)
  console.log(bar);   // ReferenceError: bar is not defined (excluded)
  console.log(baz);   // Output: 3 (accessible)
}

Checking @@unscopables Contents (informational only)

const myArray = [1, 2, 3];
const unscopables = myArray[Symbol.unscopables];

if (unscopables) {
  console.log("Array's unscopables:", Object.keys(unscopables));
} else {
  console.log("Array's unscopables is empty."); // Expected behavior
}
  • The with statement is generally discouraged due to potential scoping problems.
  • Modifying array.@@unscopables for arrays might have unintended consequences.


Explicit Object Property Access

This is the recommended approach. Always access array properties directly using their names (myArray.length, myArray[index]). This avoids potential scoping conflicts and ensures clarity.

const myArray = [1, 2, 3];
console.log(myArray.length);   // Access length property directly

Destructuring Assignment

Destructuring allows you to extract specific properties from an object or array into variables. This can be useful for creating a new object or variable set without introducing unintended conflicts:

const myArray = [1, 2, 3];
const { length } = myArray;
console.log(length); // Access the length property through the destructured variable

Using Object.assign or Spread Syntax (...)

These methods create a new object or array based on an existing one, allowing you to exclude specific properties:

const myArray = [1, 2, 3];

// Object.assign
const newArray = Object.assign({}, myArray, { length: undefined });

// Spread syntax
const newArray = [...myArray, length: undefined];  // Note: This syntax might not work in older environments

console.log(newArray); // New array without "length" property (though technically undefined)

Important Note

While these approaches can achieve similar results to array.@@unscopables, they focus on creating a new object or array without the undesired properties. They don't modify the original array itself.

  • Use explicit property access, destructuring, or object creation methods for clear and predictable code.
  • Avoid relying on the with statement due to potential scoping problems.