Movatterモバイル変換


[0]ホーム

URL:


  1. 開発者向けのウェブ技術
  2. JavaScript
  3. JavaScript リファレンス
  4. 標準組み込みオブジェクト
  5. Symbol
  6. unscopables

このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docsコミュニティーについてもっと知り、仲間になるにはこちらから。

View in EnglishAlways switch to English

Symbol.unscopables

Symbol.unscopables は静的データプロパティで、ウェルノウンシンボルSymbol.unscopables を表します。with 文はスコープオブジェクト上で、そのwith 環境内でバインドから除外されるプロパティの集合を持つプロパティを、このシンボルで検索します。

試してみましょう

const object = {  foo: 42,};object[Symbol.unscopables] = {  foo: true,};with (object) {  console.log(foo);  // 予想される結果: Error: foo is not defined}

ウェルノウンシンボルSymbol.unscopables です。

Symbol.unscopables のプロパティ属性
書込可能不可
列挙可能不可
設定可能不可

解説

[Symbol.unscopables] シンボル(Symbol.unscopables でアクセス)は、with 環境バインドでプロパティ名が字句変数として公開されるのを除外するために、任意のオブジェクトに定義することができます。なお、厳格モードでは、with 文は使用できず、このシンボルは必要ありません。

[Symbol.unscopables] オブジェクトのプロパティをtrue (または任意の真値)に設定すると、with スコープオブジェクトの対応するプロパティをスコープ対象外するため、with 本体スコープに導入されません。プロパティをfalse (または偽値)に設定すると、スコープ対象となり、字句スコープ変数として現れます。

x がスコープ対象外かどうかを判断するとき、[Symbol.unscopables] プロパティのプロトタイプチェーン全体に対してx というプロパティを呼び出します。つまり、[Symbol.unscopables] をプレーンオブジェクトとして宣言した場合、Object.prototype のプロパティ(例えばtoString など)もスコープ対象外になり、これらのプロパティが通常スコープされていると想定している古いコードでは後方互換性が発生する可能性があるということです(下記の例を参照してください)。独自の[Symbol.unscopables] プロパティでは、そのプロトタイプとしてnull を持つようにすることをお勧めします(例えばArray.prototype[Symbol.unscopables] がそうなっています)。

このプロトコルは、DOM API (Element.prototype.append() など)でも利用されています。

with 文内のスコープ

次のコードは、ES5 以下であれば正しく動作します。しかし、 ECMAScript 2015 以降では、Array.prototype.values() メソッドが導入されました。これは、with 環境内で "values" はメソッドになり、with 文の外の変数ではなくなったということです。

js
var values = [];with (values) {  // [Symbol.unscopables] が存在しない場合、ECMAScript 2015 から  // 値は Array.prototype.values になります。  // そのため、エラーが発生します。  values.push("something");}

このwith (values) を含むコードは、Array.prototype.values() が追加されたとき、Firefox において一部のウェブサイトで不具合が発生しました(Firefox Bug 883914)。さらに、将来配列メソッドが追加された場合、それが暗黙的にwith スコープを変更すると壊れる可能性があることになります。そのため、Array.prototype[Symbol.unscopables] というシンボルが導入され、ArrayArray.prototype[Symbol.unscopables] として実装され、いくつかの Array メソッドが with 文にスコープされるのを防ぎます。

オブジェクト内の unscopables

自分のオブジェクトに[Symbol.unscopables] を設定することもできます。

js
const obj = {  foo: 1,  bar: 2,  baz: 3,};obj[Symbol.unscopables] = {  // オブジェクトに `null` プロトタイプを持たせて、  // `Object.prototype` メソッドがスコープから外れないようにする  __proto__: null,  // `foo` はスコープ対象  foo: false,  // `bar` はスコープ対象外  bar: true,  // `baz` は省略。`undefined` は偽値なので、これもスコープ対象(既定値)};with (obj) {  console.log(foo); // 1  console.log(bar); // ReferenceError: bar is not defined  console.log(baz); // 3}

プロトタイプが null ではないオブジェクトを[Symbol.unscopables] として使うのは避ける

[Symbol.unscopables] のプロトタイプを削除せずに、プレーンオブジェクトとして宣言すると、微妙なバグを発生させる可能性があります。[Symbol.unscopables] の前に動作する次のコードを考えてみましょう。

js
const character = {  name: "Yoda",  toString: function () {    return "Use with statements, you must not";  },};with (character) {  console.log(name + ' says: "' + toString() + '"'); // Yoda says: "Use with statements, you must not"}

後方互換性を保つために、character にプロパティを追加するときに[Symbol.unscopables] プロパティを追加することにしました。ナイーブにこうやるかもしれません。

js
const character = {  name: "Yoda",  toString: function () {    return "Use with statements, you must not";  },  student: "Luke",  [Symbol.unscopables]: {    // Make `student` unscopable    student: true,  },};

しかし、上のコードは次のようにすると壊れてしまいます。

js
with (character) {  console.log(name + ' says: "' + toString() + '"'); // Yoda says: "[object Undefined]"}

これはcharacter[Symbol.unscopables].toString を探すと、真値であるObject.prototype.toString() を返しているため、with() 文の中のtoString() 呼び出しを、globalThis.toString() を参照させるためです。また、this なしで呼び出されているため、thisundefined であり、[object Undefined] を返しています。

このメソッドがcharacter でオーバーライドされていない場合でも、これをスコープ不能にすることでthis の値が変更されます。

js
const proto = {};const obj = { __proto__: proto };with (proto) {  console.log(isPrototypeOf(obj)); // true; `isPrototypeOf` がスコープされ `this` は `proto` になる}proto[Symbol.unscopables] = {};with (proto) {  console.log(isPrototypeOf(obj)); // TypeError: Cannot convert undefined or null to object  // `isPrototypeOf` はスコープされず `this` は undefined になる}

これを修正するには、常に[Symbol.unscopables] が、Object.prototype プロパティを含まない、スコープ対象外にしたいプロパティのみを持つするようにしてください。

js
const character = {  name: "Yoda",  toString: function () {    return "Use with statements, you must not";  },  student: "Luke",  [Symbol.unscopables]: {    // オブジェクトに `null` プロトタイプを持たせて、    // `Object.prototype` メソッドがスコープから外れないようにする    __proto__: null,    // `student` をスコープ対象外にする    student: true,  },};

仕様書

Specification
ECMAScript® 2026 Language Specification
# sec-symbol.unscopables

ブラウザーの互換性

関連情報

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp