ホームページ  >  記事  >  ウェブフロントエンド  >  javascript_javascript スキルでの削除の使用法の詳細な説明

javascript_javascript スキルでの削除の使用法の詳細な説明

WBOY
WBOYオリジナル
2016-05-16 17:37:341327ブラウズ

この記事では、著者は書籍「JavaScript オブジェクト指向プログラミング ガイド」の削除に関するエラーから始めて、さまざまなブラウザやプラグインでの削除操作の実装、制限、問題について詳しく説明します (ここでは Firebug を指します)。パフォーマンス。

主要部分を以下に翻訳します。

...本の中の主張

「関数は通常の変数と同じです。別の変数にコピーしたり、削除したりすることもできます。」

説明として次のコード スニペットを添付しました:

コードをコピーします コードは次のとおりです:

>>> var sum = function(a, b) {return a b;};
>>> var add = sum;
>>>合計;
true
>>> 合計の種類;
"未定義"

クリップ内の問題を見つけられますか? 問題は、sum 変数の削除が成功してはならず、delete 宣言が true を返してはならず、sum の typeof が未定義を返してはいけないことです。 JavaScript では、少なくともこの方法では変数を削除できないためです。

では、この例では何が起こっているのでしょうか? それはタイプミスですか、それとも冗談ですか? おそらくそうではありません。 このスニペットは、Stoyan (上記の本の著者) が簡単なテストに使用したとされる Firebug コンソールからの実際の出力です。 これは、firebug にはいくつかの異なる削除ルールがあることを示しているようです。 ストヤンを惑わしたのはファイアバグだった! それで、ここで何が起こっているのでしょうか?

この質問に答えるには、JavaScript での削除演算子の仕組み、つまり何が削除でき、何が削除できないのか、そしてその理由を理解する必要があります。 以下にその詳細を説明してみます。 Firebug の「奇妙な」動作を見て、実際にはまったく「奇妙」ではないことを理解します。変数、関数を宣言し、プロパティを割り当て、それらを削除するときの裏側を詳しく見ていきます。ブラウザの実装といくつかの有名なバグについては、ECMAScript バージョン 5 の厳密モードと、それが削除演算子の動作をどのように変更するかについても説明します。

一般に ECMAScript を指すために、以下では Javascript と ECMPScript を同じ意味で使用します (Mozilla の JavaScript™ 実装を明示的に指す場合を除く)。

予想どおり、現在、インターネット上で削除に関する説明はほとんどありません (著者注: この記事は 2010 年 1 月に書かれたものです)。 MDC (MDN]) リソースはおそらく最も詳細なリソースですが、残念ながら、上記の Firebug の奇妙な動作など、いくつかの興味深い詳細が省略されています。 MSDN ドキュメントはほとんど役に立ちません。

1. 理論 | 理論
では、なぜオブジェクトの属性を削除できるのでしょうか:

コードをコピーします コードは次のとおりです。

var x = { a: 1 };
delete x.a // true
x.a; / 未定義


ただし、変数は削除できません:
コードをコピー コードは次のとおりです。

var x = 1;
delete x; // 1

関数を削除することはできません。 :

コードをコピー コードは次のとおりです。
function x() {}; 🎜>delete x; // false;
typeof x; // "関数"


注: delete は、プロパティを削除できない場合にのみ false を返します。

これを理解するには、まず変数のインスタンス化とプロパティ属性といういくつかの概念を理解する必要があります (翻訳者注: プロパティと属性の違いについては、参考記事を参照してください。内部プロパティに変換される) - これらは JavaScript の本ではめったに言及されません。 次の段落では、これらを簡単に復習してみますが、理解するのは難しくありません。 パフォーマンスの背後にある理由に興味がない場合は、この章をスキップしてください。

1.1 コードの種類 コードの種類

ECMAScript には 3 種類の実行可能コードがあります:

1.グローバルコード グローバルコード
2.ファンクションコード ファンクションコード
3.評価コード

カテゴリはその名前の通りほとんど意味しますが、簡単に要約します:

1. ソースファイルをプログラムとみなすと、グローバルスコープ(scope)内で実行され、これがグローバルコードの一部とみなされます。 ブラウザ環境では、通常、SCRIPT 要素のコンテンツはプログラムとして解析されるため、グローバル コードとして実行されます。

2. もちろん、ブラウザ環境では、関数内で直接実行されるコードはすべて関数コードとみなされます (例:

3. 最後に、組み込み関数 eval に配置されたコードが Eval コードとして解析されます。 このタイプが特別である理由はすぐにわかります。

1.2. コード実行コンテキスト | 実行コンテキスト
ECMAScript コードは、常に特定の実行コンテキスト (コンテキスト) で実行されます。 実行スコープは、スコープと変数のインスタンス化がどのように機能するかを理解するのに役立つ抽象的なエンティティです。 上記の 3 種類の実行可能コードには、独自の実行コンテキストがあります。 関数コードが実行されるときは、コントロール エンドが関数コードの実行コンテキストに入ると言います。グローバル コードが実行されるときは、コントロール エンドがグローバル コードの実行コンテキストに入ると言います。

ご覧のとおり、実行コンテキストは論理的にはスタックです。 まず、独自の実行コンテキストを持つグローバル コードが存在する可能性があります。このコード内で関数が呼び出され、この関数も独自の実行コンテキストを持ち、この関数が別の関数を呼び出す可能性があります。 関数がそれ自体を再帰的に呼び出す場合でも、呼び出しごとに異なる実行コンテキストが入ります。

1.3. アクティベーションオブジェクトと変数オブジェクト | アクティベーションオブジェクト / 変数オブジェクト
各実行コンテキストには変数オブジェクト (Variable オブジェクト) が関連付けられています。 同様に、変数オブジェクトは抽象エンティティであり、変数のインスタンス化を記述するために使用されるメカニズムです。 興味深いのは、ソース コードの一部で宣言された変数と関数が、実際には変数オブジェクトのプロパティとして変数オブジェクトに追加されることです。

コントロールがグローバル コードの実行コンテキストに入るとき、グローバル オブジェクトは変数オブジェクトとして使用されます。 これがまさに、グローバルに宣言された変数と関数がグローバル オブジェクトのプロパティになる理由です:

コードをコピー コードは次のとおりです:

var GLOBAL_OBJECT = this;
var foo = 1;
GLOBAL_OBJECT.foo; // 1
function bar() {};
typeof GLOBAL_OBJECT.bar; "function"
GLOBAL_OBJECT.bar === bar // true

それで、グローバル変数はグローバル関数の属性になりますが、ローカル変数、つまり関数コードで宣言された変数についてはどうなるでしょうか? 実際、これは非常に単純です。これらは変数オブジェクトのプロパティにもなります。 唯一の違いは、関数コードでは変数オブジェクトがグローバル オブジェクトではなく、いわゆるアクティベーション オブジェクトであることです。 アクティブ化オブジェクトは、関数コードの実行コンテキストに入るたびに作成されます。

関数コードで宣言された変数と関数だけがアクティベーション オブジェクトの属性になるわけではありません。関数の各実パラメータ (引数。対応する仮パラメータの名前が属性名として付けられます)、および特別な Arguments オブジェクト (引数を属性名として持つ) も、アクティブ化されたオブジェクトの属性になります。 アクティベーション オブジェクトは、実際にはプログラム コードからアクセスできない内部メカニズムであることに注意してください。

コードをコピー コードは次のとおりです:

(function(foo) {
var bar = 2;
function baz() {};
/*
抽象化の過程で、
特別な'引数のオブジェクトは、関数のアクティベーション オブジェクトのプロパティになります:
ACTIVATION_OBJECT.arguments = argument;
...パラメータ 'foo' についても同様です:
ACTIVATION_OBJECT.foo; // 1
..変数 'bar' は同じです:
ACTIVATION_OBJECT.bar; // 2
...関数 'baz' は同じです:
typeof ACTIVATION_OBJECT.baz; function"
*/
}) (1);

最後に、Eval コードで宣言された変数は、コンテキストの Variable オブジェクトの属性になります。 Eval コードは、呼び出しで実行コンテキストの変数オブジェクトを単純に使用します。

コードをコピー コードは次のとおりです:

var GLOBAL_OBJECT = this;
eval ('var foo = 1');
GLOBAL_OBJECT.foo // 1;

(function() {
eval('var bar = 2');

/*
抽象化プロセス中
ACTIVATION_OBJECT.bar // 2
*/
}) ();

1.4. 属性の内部属性 | プロパティ属性
がトピックに近いです。 変数に何が起こるか (変数がプロパティになる) がわかったので、理解すべき残りの概念は、プロパティの内部プロパティ (プロパティ属性) です。 各プロパティには、0 個以上の内部プロパティ (*ReadOnly、DontEnum、DontDelete、Internal**) があります。 これらはタグと考えることができます。プロパティには特別な内部プロパティがある場合とない場合があります。 今日の議論では、DontDelete に興味があります。

変数と関数が宣言されると、それらは Variable オブジェクトのプロパティになります。つまり、アクティベーション オブジェクト (関数コード内) またはグローバル オブジェクト (グローバル コード内) になります。これらのプロパティには、内部プロパティ DontDelete が生成されます。 ただし、明示的/暗黙的に割り当てられたプロパティは DontDelete を生成しません。 これが本質的に、一部のプロパティは削除できるが、他のプロパティは削除できない理由です。

コードをコピー コードは次のとおりです:

var GLOBAL_OBJECT = this;

/* 'foo' はグローバル オブジェクトのプロパティです。
これは変数宣言によって生成されるため、内部プロパティ DontDelete
があります。これが削除できない理由です*/
var foo = 1;
delete foo; // false
typeof foo;

/* 'bar' はグローバル オブジェクトのプロパティです。

変数宣言によって生成されるため、DontDelete 子が存在します
これがどちらも削除できない理由です*/
関数 bar () { };
バーを削除; // false
バーの種類; // "関数"

/* 'baz' もグローバル オブジェクトのプロパティです。

ただし、プロパティの割り当てによって生成されるため、DontDelete はありません
。そのため、削除できます*/
GLOBAL_OBJECT。 baz = " baz";
delete GLOBAL_OBJECT.baz; // true
typeof GLOBAL_OBJECT.baz; // "未定義"

1.5、ビルトインと DontDelete ビルトインと DontDelete

これが、これがすべて起こる理由です。プロパティの特別な内部プロパティが、プロパティを削除できるかどうかを制御します。 注: 組み込みオブジェクトの一部のプロパティには DontDelete という内部プロパティがあるため、削除できません。また、特殊な引数変数 (ご存知のとおり、アクティブ化されたオブジェクトのプロパティ) には、関数インスタンスの長さ (戻りパラメータの長さ) プロパティもあります。削除しないでください:

コードをコピー コードは次のとおりです。
(function() {
/ /DontDelete
削除引数があるため、'引数' を削除できません。 // false;
引数の種類; // "object"
//DontDelete があるため関数の長さは削除できません

function f() {};
delete f.length; // false;
typeof f.length; // "番号"
}) ();

関数の引数に関連付けられたプロパティにも DontDelete があり、削除することもできません

コードをコピー コードは次のとおりです。

(function(foo,bar) {
foo を削除します。 // false
foo; // 1

バーを削除します。 // false
バー; // "ば"
}) (1,"ば");

1.6. 未宣言の変数割り当て | 未宣言の割り当て
この属性がスコープ チェーン内の他の場所で見つからない限り、未宣言の変数割り当てはグローバル オブジェクトの属性になることを覚えているかもしれません。 これで、プロパティの割り当てと変数宣言の違いが理解できました。後者は DontDelete を生成しますが、前者は生成しません。これが、宣言されていない変数の割り当てを削除できる理由です。

コードをコピー コードは次のとおりです:

var GLOBAL_OBJECT = this;

/* DontDelete を使用して、変数宣言を通じてグローバル オブジェクト属性を生成します */
var foo = 1;

/* 未宣言の変数割り当てを通じてグローバル オブジェクト プロパティを生成します。DontDelete は使用しません */
bar = 2;

delete foo; // false
delete bar; // true
注: 内部プロパティはプロパティの生成時に決定され、その後の割り当てプロセスでは既存のプロパティの内部プロパティは変更されません。 この違いを理解することが重要です。

/* 'foo' が作成されると DontDelete が生成されます */
function foo() {};

/* 後続の割り当てプロセスでは、既存の属性の内部属性は変更されません。DontDelete はまだ存在します*/
foo = 1;
delete foo; // false;
typeof foo; 「数字」

/* ただし、存在しないプロパティを割り当てる場合は、内部プロパティを持たないプロパティが作成されるため、DontDelete はありません */
this.bar = 1;
delete bar; // true;
バーの種類; // "未定義"

2. Firebug の混乱

では、firebug では何が起こっているのでしょうか? 前に説明したのではなく、コンソールで宣言された変数を削除できるのはなぜですか? 前に、Eval コードは変数宣言を処理するときに特別な動作をする、と述べました。Eval コードで宣言された変数は、実際には DontDelete を使用せずにプロパティを生成します。

コードをコピー コードは次のとおりです。

eval('var foo = 1;' );
foo; // 1
delete foo; // true
typeof foo;
同じことが関数コードにも当てはまります:


コードをコピーします コードは次のとおりです: (function () {
eval('var foo = 1;');
foo; // 1
delete foo; // true
typeof foo; // "未定義"
}) ();



これが Firebug の予期せぬ動作の理由です。 コンソール内のすべてのデバッグ テキストは、グローバル コードや関数コードではなく、Eval コードでコンパイルおよび実行されているように見えます。 明らかに、変数宣言は最終的に DontDelete なしで属性を生成するため、属性は削除できます。 したがって、通常のグローバル コードと Firebug コンソールのコードの違いに注意してください。
2.1. eval を介して変数を削除する | eval を介して変数を削除する

この興味深い eval 動作を ECMAScript の別の側面と組み合わせることで、本来は削除できない属性を技術的に削除できます。 この側面は関数宣言に関するものです。関数宣言は、同じ実行コンテキスト内の同じ名前の変数をオーバーライドできます:


コードをコピー コードは次のとおりです。function x() { };
var x ;
typeof x; // “function”


では、なぜ関数宣言が優先され、同じ名前 (つまり、同じプロパティ) の変数をオーバーライドできるのでしょうか。変数オブジェクトの)? これは、関数宣言が変数宣言の後にインスタンス化されるため、オーバーライドできるためです。
(翻訳者注: 関数宣言は、宣言されたものの割り当てられていない同じ名前の変数のみを上書きできます。宣言時に値が割り当てられている場合 (例: var x = 1)、値を割り当てるプロセスはこれは関数が初期化された後であり、次のように関数宣言は代わりに代入によってカバーされます:)


コードをコピー コードは次のとおりです: var x = 1;
function x() { };
typeof x; // "number"

関数宣言は属性の値を置き換えるだけでなく、その内部属性も置き換えます。 eval を介して関数を宣言すると、この関数も前の関数を独自の内部プロパティに置き換えます。 eval で宣言された変数によって生成された属性には DontDelete がないため、この関数をインスタンス化すると、「理論的には」元の属性の既存の DontDelete 内部属性が削除され、この属性を削除できるようになります (もちろん、値もポイントします)新しく生成された関数)。

コードをコピー コードは次のとおりです:

var x = 1;
/ *削除できません、'x' には DontDelete*/
delete x; // false
typeof x; // "number"

eval('function x() { }');
/* 属性 'x' は function を指しており、DontDelete は存在しないはずです */
typeof x; // "function"delete x ; // 'true' である必要があります;
typeof x; // "未定義" である必要があります

残念ながら、このなりすまし手法は、試したどのブラウザでも成功しませんでした。 ここに何かが欠けているか、動作が非常に微妙なので個々のブラウザがそれに気付かない可能性があります。

(翻訳者注: ここでの問題は、関数宣言と変数宣言の間のオーバーライドが、指す値の変更のみであるのに対し、内部属性 DontDelete は最初の宣言で決定され、もはや変更されないのに対し、変数は変更されないことです。 eval や関数内で宣言されている場合、削除できるのは外部コンテキストで宣言されていない部分のみです。 eval は関数であるため、常に外部コンテキストで他の変数や関数が宣言された後に呼び出されます。関連する内部属性 値へのポインタのみがカバーされることも確認されています:)


コードをコピーします コードは次のとおりです。以下のように:
/* 代入処理が宣言処理と評価実行処理の後であるため、最初のアラートは「未定義」を返します。
の位置が異なるため、2 番目のアラートは「false」を返します。 x宣言はevalの後、
ただし、evalは変数宣言後に実行されるため削除できません*/
eval('alert( x );alert(delete x) ');
var x = 1;

3. ブラウザのコンプライアンス

動作の仕組みを理解することは重要ですが、実際の実装はさらに重要です。 ブラウザは変数/プロパティを作成および削除するときにこれらの標準に従っていますか? ほとんどの場合、そうです。

グローバル コード、関数コード、および Eval コードの準拠性をチェックするための

簡単なテスト ユニット を作成しました。 テスト ユニットは、削除操作の戻り値と属性が期待どおりに削除されるかどうかもチェックします。 delete の戻り値は、実際の結果ほど重要ではありません。重要なのは、DontDelete を使用してプロパティが削除されたかどうかです。

最新のブラウザは通常、削除ルールに従っており、Opera 7.54、Firefox 1.0、Safari 3.1.2、Chrome 4 はすべてテストに合格しています。

Safari 2.x および 3.0.4 には関数の引数の削除に関する問題があり、これらのプロパティは DontDelete なしで作成されているため、削除できるようです。 Safari 2.x には他にも問題があります - 参照なしで削除するとエラーが発生します (delete 1 など) (翻訳者注: IE にもこれがあります) (不思議なことに、変数宣言は正常に動作します)。 eval は削除できなくなります (ただし、eval 内の関数宣言は正常です)。

Safari と同様に、Konqueror (4.3 ではなく 3.5) にも、参照なしの削除と引数の削除に関して同じ問題があります。

3.1、Gecko DontDelete バグ

Gecko 1.8.x ブラウザ - Firefox 2.x、Camino 1.x、Seamonkey 1.x など - 興味深いバグがあります。A プロパティへの値の明示的な割り当ては、プロパティが変数または関数を介して宣言されている場合でも、DontDelete を削除します。

コードをコピー コードは次のとおりです。
function foo() { };
delete foo ; // false;
typeof foo; // "関数"
this.foo = 1;

delete foo // true
typeof foo; // "未定義"

驚くべきことに、IE5.5-8 も、非参照を削除するとエラーがスローされることを除いて、ほとんどのテストに合格します (例: 古い Safari と同じように 1 を削除)。 ただし、すぐにはわかりませんが、IE には実際にはさらに深刻なバグがあり、これらのバグはグローバル オブジェクトに関連しています。

4. IE のバグ

IE (少なくとも IE6-8) では、次の式は (グローバル コードで) 例外をスローします:

Copy code コードは次のとおりです:

this.x = 1;
delete x; // TypeError: オブジェクトはこのアクションをサポートしていません

そして、これがもう 1 つです:

コードをコピー コードは次のとおりです:

var x =1;
delete this.x ; // TypeError: 'this.x' を削除できません
// 翻訳者注: この例外は IE8 でスローされ、上記と同じ例外が IE6 および 7 でスローされます

これは、IE のグローバル コード内の変数宣言がグローバル オブジェクトの同名のプロパティを生成していないことを示しているようです。 代入 (this.x = 1) によって作成され、delete x によって削除されたプロパティは例外をスローします。変数宣言 (var x = 1) によって作成され、delete this.x によって削除されたプロパティは、別の例外をスローします (Translator's Press :エラー メッセージは IE6 および 7 で上記と同じです)。

しかしそれだけではありません。実際には、明示的な代入によって作成されたプロパティは、削除時に常に例外をスローします。 これは単なるバグではなく、作成されたプロパティには DontDelete 内部プロパティがあるように見えますが、ルールによれば、これは禁止されています。

コードをコピー コードは次のとおりです:

this.x = 1;
delete this. x; // TypeError: オブジェクトはこのアクションをサポートしていません
delete x; // TypeError: オブジェクトはこのアクションをサポートしていません

一方、宣言されていない変数の割り当て (グローバル オブジェクトも生成する属性) は、IE では実際に通常どおり削除できます。

コードをコピー コードは次のとおりです:
x = 1;
delete x ; // true

しかし、このキーワードで削除しようとすると (delete this.


コードは次のとおりです:

要約すると、「delete this.x」はグローバル コードでは決して成功しないことがわかります。 属性が明示的な割り当てによって生成される場合 (this.x = 1)、例外がスローされます。変数の宣言または宣言解除によって属性が生成される場合 (var x = 1 または x = 1)、別の例外がスローされます。 一方、Delete x は、明示的な代入によってプロパティが生成された場合 (this.x = 1) にのみ例外をスローします。



9 月に私はこの問題について議論しました
。そこで Garrett Smith

は、IE ではグローバル変数オブジェクト (グローバル変数オブジェクト) が JScript オブジェクトとして実装されており、グローバル オブジェクトはHost オブジェクトの実装によって表されます。

この理論をある程度確認するために、いくつかのテストを実行できます。 this と window は同じオブジェクトを参照しているように見えますが ('===' 演算子が信頼できる場合)、Variable オブジェクト (関数宣言の基礎) は this によって参照されるオブジェクトとは異なることに注意してください。

コードをコピーします

コードは次のとおりです。

function getBase() { return this; } ; getBase() === this.getBase(); // falsethis.getBase() === this.getBase(); // truewindow.getBase(); .getBase(); // true
window.getBase() === getBase() // false

5. 誤解

物事がどのように機能するかを理解することの重要性を過小評価することはできません。 インターネット上で削除操作に関する誤解をいくつか見かけました。 たとえば、Stackoverflow の回答 (および非常に上位のもの) では、「ターゲットがオブジェクト プロパティではない場合、削除は何も行われないことになっている」と説明されています。 削除操作の中核を理解したので、この答えが間違っていることは明らかです。 delete は、変数とプロパティ (実際、これらは削除操作における参照です) を区別せず、DontDelete (およびプロパティが既に存在するかどうか) のみを考慮します。

6. 'delete' とホスト オブジェクト | 'delete' とホスト オブジェクト

削除アルゴリズムは大まかに次のようなものです:

1. オペランドが参照でない場合は true を返します
2. オブジェクトに同じ名前の **直接プロパティ** がない場合は、true を返します (ご存知のとおり、オブジェクトはグローバル オブジェクトまたはアクティベーション オブジェクト)
3. プロパティが既に存在するが DontDelete がある場合は、false
を返します。それ以外の場合は、プロパティを削除して true
を返します。ホスト オブジェクトは予測できない可能性があります。 実際、これには何も問題はありません。ホスト オブジェクトは (特定のルールに従って) 読み取り (内部 [[Get]] メソッド)、書き込み (内部 [[Write]] メソッド)、削除 (内部 [ [削除]] ]メソッド)など。 カスタム [[削除]] 動作を許可すると、ホスト オブジェクトで混乱が生じます。

IE では、特定のオブジェクト (ホスト オブジェクトとして実装されているもの) のプロパティを削除するときに例外がスローされるという問題がいくつか確認されています。 Firefox の一部のバージョンは、window.location を削除しようとすると例外をスローします (翻訳者注: IE も例外をスローします)。 同様に、Firefox で起こったことなど、一部のホスト オブジェクトの delete の戻り値は信頼できません (翻訳者注: Chrome でも同じ結果が得られます。IE では例外がスローされます。Opera と Safari では削除が許可されていますが、削除後に呼び出すことはできません)。 ) は暫定的に「正常」であると考えられていますが、以下の説明から判断すると、実際には削除できない属性が削除されますが、以前のブラウザでは削除されません):

コードをコピー コードは次のとおりです:
/* 'alert' は 'window' の直接のプロパティです ('hasOwnProperty が信じられる場合) ') */
window.hasOwnProperty('alert') // true
; delete window.alert; // true

typeof window.alert; // "関数"

delete window.alert は true を返しますが、このプロパティにはこの結果を生成するための条件はありません (上記のアルゴリズムに従って)。これは参照に解決されるため、最初のステップで true を返すことはできません。したがって、2 番目のステップでは true を返すことができません。唯一 true を返すことができるのは、アルゴリズムが最後のステップに到達して実際に属性を削除するときですが、実際には削除されていません。 (訳者注:いいえ、確かにオペラやサファリでは削除されていました…)。

つまり、この話は、ホスト オブジェクトを決して信頼してはいけないということになります。

7. ES5 厳密モード | ES5 厳密モード

では、厳密モードは ECMAScript バージョン 5 に何をもたらすのでしょうか? これらの制限の一部については現在説明しています。 SyntaxError は、削除操作が変数/関数パラメータ/関数宣言への直接参照を指している場合にスローされます。 さらに、プロパティに内部プロパティ [[Configurable]] == false がある場合、TypeError がスローされます:

コードをコピー コードは次のとおりです。
(function(foo) {
"use strict "; //関数
で strict モードを有効にする var bar;

function baz;
delete foo; // 関数パラメータが削除された場合の SyntaxError
delete bar; // 変数が削除された場合の SyntaxError 、関数宣言によって作成された変数を削除する場合

/* 関数インスタンスの長さは [[Configurable]]: false */

delete (function() {}).length; // TypeError

}) ();

さらに、厳密モードでは、宣言されていない変数 (つまり、未解決の参照) を削除すると SyntaxError がスローされます。同様に、同じモードで宣言されていない割り当ても例外 (ReferenceError ) をスローします。

コードをコピー コードは次のとおりです:

"use strict";
delete i_dont_exist; // SyntaxError
i_dont_exist_either = 1; // ReferenceError

前に示した変数、関数宣言、パラメーターの例を見て、これらすべての制限には意味があることが理解できたと思います。 厳密モードでは、これらの問題を単に無視するのではなく、より積極的かつ記述的なアプローチが取られます。

8. まとめ|

この記事はすでにかなり長いため、他のこと (たとえば、delete による配列項目の削除とその影響) については説明しません。 MDC/MDN の記事を確認するか、仕様を読んで自分でテストすることができます。

JavaScript での削除の仕組みを簡単にまとめます:

•変数と関数の宣言は、Activation グローバル オブジェクトのプロパティです。
•プロパティには内部プロパティがあり、そのうちの 1 つである DontDelete は、プロパティを削除できるかどうかを決定します。
•グローバル コードまたは関数コード内の変数および関数宣言は、DontDelete を使用して属性を生成します。
•関数パラメータもアクティベーションオブジェクトの属性であり、DontDeleteも持ちます。
•Eval コード内の変数と関数の宣言は、DontDelete を使用せずに属性を生成します。
• 新しい未宣言のプロパティは空の内部プロパティで生成されるため、DontDelete は生成されません。
•ホスト オブジェクトは、希望する方法で削除プロセスに応答することができます。

原文: 削除の理解翻訳: javascript での削除翻訳者: justjavac

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。