私もこれを知りません、家に帰って農場に行きます。
コードコピーは次のとおりです。
thisisobject [key]を削除する
または
thisisobject.keyを削除します
ちなみに、削除の使用について話しましょう
数週間前、私はStoyan Stefanovのオブジェクト指向のJavaScriptの本を読む機会がありました。この本はAmazon(12件のレビュー、5つ星)で高く評価されているので、それがそのような推奨される本であるかどうかを知りたいと思っていたので、機能の章を読み始めました。この本が物事を説明する方法に本当に感謝しています。例は非常に美しく段階的な方法で整理されており、初心者でさえこの知識を簡単に習得できるようです。しかし、ほとんどすぐに、私は章全体で興味深い誤解を発見しました - 機能的機能の削除。また、他のエラー(関数宣言と関数式の違いの違いなど)もありますが、現時点では説明しません。
本は主張している:
「関数は通常の変数のように扱われます。異なる変数にコピーすることも、削除されます。」この説明には例が添付されています。
コードコピーは次のとおりです。
var sum = function(a、b){return a + b;}
var add = sum;
合計を削除します
真実
typeof合計;
"未定義"
欠落しているセミコロンを無視してください、これらのコードのエラーがどこにあるかを見ることができますか?明らかに、エラーは、合計変数を削除する操作が成功しないことです。削除式はtrueを返すべきではなく、typeof sumは「未定義」を返すべきではありません。これはすべて、JavaScriptで変数を削除することが不可能だからです。少なくとも、この宣言の方法では不可能です。
それで、この例では何が正確に起こったのでしょうか?バグですか?または特別な使用法?おそらくそうではありません。このコードは実際にはFireBugコンソールの実際の出力であり、Stoyanはそれを迅速なテストのためのツールとして使用していたに違いありません。 Firebugが他の削除ルールに従うようなものです。ストーヤンが迷ったのはファイアーバグです!それで、ここで何が起こったのですか?
この質問に答える前に、最初にJavaScriptで削除オペレーターがどのように機能するかを理解する必要があります。削除できるものと削除できないものは何ですか?今日は、これを詳細に説明しようとします。 Firebugの「奇妙な」振る舞いを見て、それほど奇妙ではないことに気付きます。変数、関数、属性に値を割り当てて削除する舞台裏で隠されているものをより深く掘り下げます。ブラウザの互換性と、最も有名なバグのいくつかを見ていきます。また、ES5の厳密なパターンと、削除演算子の動作をどのように変えるかについても説明します。
JavaScriptとECMAScriptを交換しますが、どちらもECMAScriptを意味します(MozillaのJavaScriptの実装が明らかでない限り)
予想通り、インターネットでは、削除の説明は非常に少ないです。 MDCの記事はおそらく理解するのに最適なリソースですが、残念ながら、このトピックの興味深い詳細がいくつかありません。奇妙なことに、忘れられたものの1つは、ファイアーバグの奇妙な症状の理由です。また、MSDN参照は、これらの側面ではほとんど役に立たない。
理論
したがって、なぜオブジェクトのプロパティを削除できるのですか。
コードコピーは次のとおりです。
var o = {x:1};
OXを削除します。 // 真実
牛; // 未定義
しかし、このように宣言されたオブジェクトは削除することはできません。
コードコピーは次のとおりです。
var x = 1;
xを削除します。 // 間違い
x; // 1
または関数:
コードコピーは次のとおりです。
関数x(){}
xを削除します。 // 間違い
typeof x; // "関数"
注:プロパティを削除できない場合、削除演算子はfalseのみを返します。
これを理解するには、まず、さまざまなインスタンスと属性プロパティに関するこれらの概念を習得する必要があります。これらの概念は、残念ながらJavaScriptの本ではめったに言及されません。次のいくつかの段落で、これらの概念を簡単に確認しようとします。これらの概念は理解するのが難しいです! 「なぜこれらのことがこのように機能するのか」を気にしない場合は、この章をスキップしてください。
コードの種類:
ECMAScriptには、3つの異なるタイプの実行可能コードがあります:グローバルコード、関数コード、および評価コード。これらのタイプは、名前の観点から多かれ少なかれ自明です。簡単な概要を以下に示します。
ソースコードの一部がプログラムと見なされる場合、それはグローバル環境で実行され、グローバルコードと見なされます。ブラウザ環境では、スクリプト要素の内容は通常プログラムとして解釈されるため、グローバルコードとして実行されます。
関数で直接実行されるコードは、明らかに関数コードと見なされます。ブラウザでは、イベントプロパティのコンテンツ(<p onclick = "...">など)は通常、関数コードとして解釈されます。
最後に、組み込み関数評価に適用されるコードテキストは、評価コードとして解釈されます。すぐに、このタイプが特別な理由がわかります。
実行コンテキスト:
ECMAScriptコードが実行されると、通常、特定の実行コンテキストで発生します。実行コンテキストは、やや抽象的なエンティティの概念であり、スコープと可変インスタンスがどのように機能するかを理解するのに役立ちます。 3つの実行可能性コードのそれぞれについて、それに対応する実行コンテキストがあります。関数が実行されると、「プログラム制御が関数コードの実行コンテキストに入る」と言います。グローバルコードの一部が実行されると、プログラム制御はグローバルコードなどの実行コンテキストに入ります。
ご覧のとおり、実行コンテキストは論理的にスタックを形成できます。まず、グローバルコードと独自の実行コンテキストがある場合があります。その後、このコードは、その(関数)実行コンテキストを持つ関数を呼び出す場合があります。この関数は別の関数などを呼び出すことができます。関数が再帰的に呼ばれている場合でも、呼び出されるたびに新しい実行コンテキストに入力されます。
Active Object(Activation Object) /変数オブジェクト:
各実行コンテキストには、それに関連付けられたいわゆる変数オブジェクトがあります。実行コンテキストと同様に、可変オブジェクトは抽象的なエンティティであり、可変インスタンスを記述するために使用されるメカニズムです。興味深いことに、ソースコードで宣言された変数と関数は、通常、この変数オブジェクトにプロパティとして追加されます。
プログラム制御がグローバルコードの実行コンテキストに入ると、グローバルオブジェクトが可変オブジェクトとして使用されます。これが、グローバルに宣言された関数変数がグローバルオブジェクトプロパティになる理由です。
コードコピーは次のとおりです。
/ *グローバルスコープの場合、「これはグローバルオブジェクトを指すことを覚えておいてください */
var global_object = this;
var foo = 1;
Global_object.foo; // 1
foo === global_object.foo; // 真実
function bar(){}
typeof global_object.bar; // "関数"
Global_object.bar === bar; // 真実
OK、グローバル変数はグローバルオブジェクトのプロパティになりますが、ローカル変数(関数コードで定義されているもの)はどうなりますか?実際、それらは非常に同様に動作します。可変オブジェクト(可変オブジェクト)のプロパティになります。唯一の違いは、関数コードの場合、変数オブジェクトはグローバルオブジェクトではなく、いわゆるアクティベーションオブジェクトであることです。アクティブオブジェクトは、関数コードの実行コンテキストに入るたびに作成されます。
関数コードで宣言された変数と関数だけでなく、アクティブオブジェクトのプロパティになります。これは、各関数パラメーター(対応する正式なパラメーターに対応する名前)と特別な引数オブジェクト(引数の名前)でも発生します。アクティブオブジェクトは内部説明メカニズムであり、プログラムコードでアクセスできないことに注意してください。
コードコピーは次のとおりです。
(function(foo){
var bar = 2;
関数baz(){}
/*
抽象的には、
特別な「引数」オブジェクトは、関数のアクティベーションオブジェクトを含むプロパティになります。
Activation_object.arguments; //引数オブジェクト
...議論「foo」と同様に:
Activation_object.foo; // 1
...変数「bar」と同様に:
Activation_object.bar; // 2
...ローカルで宣言された関数と同様に:
typeof activation_object.baz; // "関数"
*/
})(1);
最後に、評価コードで宣言された変数は、発信者のコンテキストで変数オブジェクトのプロパティになります。 Eval Codeは、コードを呼び出すコードの実行コンテキストで変数オブジェクトを使用するだけです。
コードコピーは次のとおりです。
var global_object = this;
/* `foo`は、コンテキスト変数オブジェクトを呼び出すプロパティとして作成されます。
この場合、グローバルオブジェクト */
eval( 'var foo = 1;');
Global_object.foo; // 1
(関数(){
/* `bar`は、コンテキスト変数オブジェクトを呼び出すプロパティとして作成されます。
この場合、関数を含むアクティベーションオブジェクト */
eval( 'var bar = 1;');
/*
抽象的には、
Activation_object.bar; // 1
*/
})();
プロパティ属性
私たちはほとんどここにいます。変数で何が起こっているのか(プロパティになる)ことをよく知っているので、理解されるべき唯一の概念はプロパティ属性です。各属性には、次のセットから選択された0つ以上のプロパティを持つことができます:Readonly、Dontenum、dontdeleteおよびinternal。それらをフラグと考えることができます - プロパティに存在するかどうかは存在するか、存在しない機能です。今日の議論のために、私たちはdontdeleteにのみ興味があります。
宣言された変数と関数は、変数オブジェクトの属性(または関数コードのアクティブオブジェクト、またはグローバルコードのグローバルオブジェクト)になると、これらの属性はdontDelete属性属性で作成されます。ただし、明示的な(または暗黙の)属性は、dontdelete属性には含まれません。これが、一部の属性を削除できるが、他の属性を削除することはできない理由です。
コードコピーは次のとおりです。
var global_object = this;
/* `foo`はグローバルオブジェクトのプロパティです。
可変宣言を介して作成されているため、DontDelete属性も作成されます。
これが削除できない理由です。 */
var foo = 1;
fooを削除します。 // 間違い
タイプフー; // "番号"
/* `bar`はグローバルオブジェクトのプロパティです。
関数宣言を介して作成されているため、DontDelete属性も作成されます。
これが削除されない理由です。 */
function bar(){}
バーを削除します。 // 間違い
Typeof Bar; // "関数"
/* `baz`もグローバルオブジェクトのプロパティです。
ただし、プロパティ割り当てを介して作成されるため、dontdelete属性はありません。
これが削除できる理由です。 */
global_object.baz = 'blah';
global_object.bazを削除します。 // 真実
typeof global_object.baz; // "未定義"
組み込みのオブジェクトとdontdelete
したがって、これはすべてです(dontdelete):このプロパティを削除できるかどうかを制御するプロパティの特別なプロパティ。いくつかの内蔵オブジェクトは、dontdeleteを含むように指定されているため、削除できないことに注意してください。たとえば、特別な引数変数(または、私たちが知っているように、アクティブオブジェクトの特性)にはdontdeleteがあります。関数インスタンスの長さプロパティには、DontDeleteプロパティもあります。
コードコピーは次のとおりです。
(関数(){
/ *「引数」を削除できません。
引数を削除します。 // 間違い
Typeof引数; // "物体"
/*関数の「length」を削除できません。また、dontdelete */
関数f(){}
F.Lengthを削除します。 // 間違い
型f.length; // "番号"
})();
関数パラメーターに対応する属性には、その確立以来、dontdelete機能もあるため、削除することはできません。
コードコピーは次のとおりです。
(function(foo、bar){
fooを削除します。 // 間違い
foo; // 1
バーを削除します。 // 間違い
バー; //「何とか」
})(1、 'blah');
宣言されていない割り当て:
また、宣言されていない割り当てが、グローバルオブジェクトの前にこのスコープチェーンの他の場所でプロパティが見つかっていない限り、グローバルオブジェクト上にプロパティを作成することを覚えておくことがあります。そして今、私たちはプロパティの割り当てと変数宣言の違いを知っています - 後者はdontdeleteプロパティを設定しますが、前者はそうではありません。宣言されていない割り当てが削除可能なプロパティを作成する理由を明確にしなければなりません。
コードコピーは次のとおりです。
var global_object = this;
/*可変宣言を介してグローバルプロパティを作成します。プロパティにはdontdelete */
var foo = 1;
/*宣言されていない割り当てを介してグローバルプロパティを作成します。プロパティにはdontdelete */
bar = 2;
fooを削除します。 // 間違い
タイプフー; // "番号"
バーを削除します。 // 真実
Typeof Bar; // "未定義"
注:プロパティは、属性が作成されたときに決定され、その後の割り当ては既存の属性のプロパティを変更しません。この違いを理解することは非常に重要です。
コードコピーは次のとおりです。
/ * `foo`はdontdeleteのあるプロパティとして作成されます */
functionfoo(){}
/*後の割り当ては属性を変更しません。 dontdeleteはまだそこにあります! */
foo = 1;
fooを削除します。 // 間違い
タイプフー; // "番号"
/*しかし、存在しないプロパティに割り当てる、
空の属性でそのプロパティを作成します(そしてdontdeleteなしで) */
this.bar = 1;
バーを削除します。 // 真実
Typeof Bar; // "未定義"
Firebugの混乱:
Firebugはどうなりますか?コンソールで宣言された変数を削除できるのはなぜですか?これは私たちが以前に学んだことに反していませんか?さて、前に言ったように、評価コードは、可変宣言に直面しているときに特別なパフォーマンスを持っています。評価で宣言された変数は、実際にはdontdelete属性のない属性として作成されます。
コードコピーは次のとおりです。
eval( 'var foo = 1;');
foo; // 1
fooを削除します。 // 真実
タイプフー; // "未定義"
同様に、同様に、関数コードで呼び出された場合:
コードコピーは次のとおりです。
(関数(){
eval( 'var foo = 1;');
foo; // 1
fooを削除します。 // 真実
タイプフー; // "未定義"
})();
これは、火菌の異常な挙動の基礎です。コンソール内のすべてのテキストは、グローバルまたは関数コードではなく、評価コードとして解析および実行されます。明らかに、ここで宣言されたすべての変数は、最終的にはdontdelete属性のないプロパティになるため、それらはすべて簡単に削除できます。グローバルコードとFireBugコンソールの違いを理解する必要があります。
評価を介して変数を削除します:
ECMAScriptの別の側面と相まって、この興味深い評価動作により、技術的には「無関係」のプロパティを削除できるようになります。関数宣言に関する1つのことは、同じ実行コンテキストで同じ名前の変数をオーバーライドできることです。
コードコピーは次のとおりです。
関数x(){}
var x;
typeof x; // "関数"
関数宣言が優先度を取得し、同じ名前(つまり、変数オブジェクトの同じプロパティ)で変数を上書きする方法に注意してください。これは、機能宣言が変数宣言後にインスタンス化され、それらを上書きすることが許可されているためです(変数宣言)。関数宣言は、プロパティの価値を置き換えるだけでなく、そのプロパティのプロパティを置き換えます。 evalを介して関数を宣言する場合、その関数は、元の(置き換えられた)プロパティのプロパティを独自のプロパティに置き換える必要があります。また、evalを介して宣言された変数は、dontdelete属性のないプロパティを作成するため、この新しい関数をインスタンス化すると、プロパティを削除できるように、既存のdontdelete属性が実際に削除されます(そして、明らかに、新しく作成された機能に値を指します)。
コードコピーは次のとおりです。
var x = 1;
/ *削除できません、 `x`はdontdelete */
xを削除します。 // 間違い
typeof x; // "番号"
eval( 'function x(){}');
/ * `x`プロパティは機能を参照します。
typeof x; // "関数"
xを削除します。 //「True」でなければなりません
typeof x; //「未定義」にする必要があります
残念ながら、この「欺ception」は現時点では機能しません。たぶん私はここに何かが足りないのかもしれませんし、動作があまりにもあいまいであるかもしれません。
ブラウザの互換性:
理論上は、物事がどのように機能するかを理解するのに役立ちますが、実践は最も重要なことです。ブラウザは、変数/プロパティの作成/削除に関して標準に従いますか?答えは次のとおりです。ほとんどの場合、はい。
グローバルコード、機能コード、評価コードの下でのテストを含む、削除演算子とのブラウザ互換性をテストするための簡単なテストセットを書きました。テストセットは、削除演算子の返品値と属性値(動作する必要がある)が本当に削除されているかどうかを確認します。削除の返品値は、その実際の結果ほど重要ではありません。 deleteがfalseの代わりにtrueを返す場合、これは重要ではありません。重要なのは、dontdelete属性を持つ属性が削除されないということです。逆も同様です。
通常、最新のブラウザは非常に互換性があります。前述の評価機能とは別に、次のブラウザはすべてのテストセットに合格しました:Opera 7.54+、Firefox 1.0+、Safari 3.1.2+、Chrome 4+。
Safari 2.xおよび3.0.4は、関数パラメーターを削除するときに問題があります。これらのプロパティはdontdeleteなしで作成されているようであるため、削除できます。 Safari 2.xにはより多くの問題があります - 非参照変数(削除1など)を削除すると例外がスローされます。関数宣言は、削除可能なプロパティを作成します(ただし、奇妙なことに、可変宣言はそうではありません)。評価の変数宣言は非誘惑になります(ただし、関数宣言は削除可能です)。
Safariと同様に、Konqueror(4.3ではなく3.5)は、非参照タイプ(削除1など)を削除するときに例外をスローし、関数変数を削除可能にします。
翻訳者のメモ:
Chrome、Firefox、IEの最新バージョンをテストし、基本的に23および24を除く他のすべてのパスが失敗する状況を保持しました。同時に、UCといくつかのモバイルブラウザをテストしました。 Nokia E72の組み込みブラウザーを除き、15と16も故障している場合、他の組み込みブラウザーはほとんどデスクトップブラウザーと同じです。しかし、BlackBerry Curve 8310/8900の組み込みブラウザが23を通過できることに言及する価値があります。
Gecko dontdeleteバグ:
Gecko 1.8.xブラウザー-Firefox 2.x、Camino 1.x、Seamonkey 1.xなど - 非常に興味深いバグを示しています。このプロパティが変動宣言または機能宣言によって作成された場合でも、プロパティの明示的な割り当てはdontdeleteプロパティを削除します。
コードコピーは次のとおりです。
functionfoo(){}
fooを削除します。 // false(予想どおり)
タイプフー; // "function"(予想どおり)
/ *次に、プロパティに明示的に割り当てます */
this.foo = 1; // ontdelete属性を誤ってクリアします
fooを削除します。 // 真実
タイプフー; // "未定義"
/ *プロパティを暗黙的に割り当てるときにこれは起こらないことに注意してください */
function bar(){}
bar = 1;
バーを削除します。 // 間違い
Typeof Bar; //「番号」(割り当てはプロパティを置き換えましたが)
驚くべきことに、Internet Explorer 5.5-8は完全なテストセットに合格しましたが、非参照タイプ(削除1など)を削除すると例外がスローされます(古いSafariのように)。ただし、IEにはより深刻なバグがありますが、それほど明白ではありません。これらのバグはグローバルオブジェクトに関連しています。
すなわちバグ:
この章全体がインターネットエクスプローラーのバグについて説明していますか?おお!すごい!
IE(少なくとも6-8)では、次の式が例外をスローします(グローバルコードで実行された場合):
this.x = 1;
xを削除します。 // typeRror:オブジェクトはこのアクションをサポートしていません
これもそうですが、異なる例外を投げます。これにより、物事はさらに面白くなります。
var x = 1;
this.xを削除します。 // typeRror: 'this.x'を削除できません
これは、IEでは、グローバルコードの変数宣言はグローバルオブジェクトに属性を作成しないように見えます。割り当て(this.x = 1)で属性を作成し、その後削除して削除すると、エラーがスローされます。宣言(var x = 1)によって属性を作成し、その後削除すると、別のエラーがスローされます。
しかし、それだけではありません。明示的な割り当てによってプロパティを作成すると、実際には削除されたときに常にスロー例外が発生します。ここにエラーがあるだけでなく、作成されたプロパティにはdontdelete属性があるように見えますが、もちろんそうではありません。
this.x = 1;
this.xを削除します。 // typeRror:オブジェクトはこのアクションをサポートしていません
typeof x; // "number"(まだ存在し、本来あるべき削除されていません!)
xを削除します。 // typeRror:オブジェクトはこのアクションをサポートしていません
typeof x; //「番号」(再び削除されませんでした)
これで、IEの下では、未申告の割り当て(グローバルオブジェクトにプロパティを作成する必要がある)が削除可能なプロパティを作成すると思います。
x = 1;
xを削除します。 // 真実
typeof x; // "未定義"
ただし、グローバルコード(this.xを削除)でこのリファレンスを介してこのプロパティを削除すると、同様のエラーがポップアップします。
x = 1;
this.xを削除します。 // typeRror: 'this.x'を削除できません
この動作を要約したい場合は、削除を使用すると、グローバルコードから変数を削除することは成功しないようです。質問のプロパティが明示的な割り当て(this.x = 1)によって作成された場合、削除はエラーをスローします。プロパティが宣言されていない割り当て(x = 1)または宣言(var x = 1)によって作成された場合、削除は別のエラーをスローします。
一方、Xを削除すると、エラーは、明示的な割り当てによってプロパティが作成された場合にのみスローする必要があります。これはX =1。宣言(var x = 1)によってプロパティが作成された場合、削除操作が発生せず、削除操作は正しくfalseを返します。プロパティが宣言されていない割り当て(x = 1)によって作成されている場合、削除操作は予想どおりに機能します。
私はこの問題について再び9月に考えました。ギャレット・スミスは、IEの下で、
「グローバル変数オブジェクトはJScriptオブジェクトとして実装され、グローバルオブジェクトはホストによって実装されます。」
ギャレットは、エリック・リパートのブログエントリを参照として使用しました。
いくつかのテストを実装することにより、多かれ少なかれこの理論を確認できます。これとウィンドウは同じオブジェクト(===演算子を信頼できる場合)を指しているように見えるが、変数オブジェクト(関数宣言が位置するオブジェクト)は、このポイントとは異なることに注意してください。
コードコピーは次のとおりです。
/ *グローバルコード */
function getBase(){return this; }
getBase()=== this.getBase(); // 間違い
this.getBase()=== this.getBase(); // 真実
window.getBase()=== this.getBase(); // 真実
window.getBase()=== getBase(); // 間違い
誤解:
物事がそのように機能する理由を理解することの美しさは、過小評価されないことです。インターネット上の削除オペレーターについての誤解を見てきました。たとえば、stackoverflowの答え(驚くほど高い評価を伴う)は、自信を持って説明します
「ターゲットオペランドがオブジェクトプロパティではない場合、削除は動作する必要があります。」
削除操作動作のコアを理解したので、この答えのエラーは明らかになります。 deleteは、変数と属性を区別せず(実際、削除の場合、それらは両方とも参照タイプです)、実際にはdontdelete属性(および属性自体が存在するかどうか)のみを気にします。
また、さまざまな誤解が互いに反論しているのを見るのも非常に興味深いことです。同様に、ある人は最初に変数のみを削除することを提案しました(評価で宣言されていない限りこれは機能しません)。一方、別の人は、削除がグローバルコードの変数を削除するために使用する方法にバグ修正を提供しましたが、関数コードでは提供されませんでした。
インターネット上のJavaScriptの説明に特に注意してください。理想的な方法は、問題の本質を常に理解することです。 ;)
オブジェクト(ホストオブジェクト)を削除してホストします:
削除アルゴリズムはおおよそこのようなものです。
オペランドが参照タイプでない場合はtrueを返します
オブジェクトにこの名前の直接的な属性がない場合は、trueを返します(私たちが知っているように、オブジェクトはアクティブオブジェクトまたはグローバルオブジェクトになります)
プロパティが存在するが、dontdelete属性がある場合は、falseを返します
他の場合、属性を削除してtrueを返します
ただし、ホストオブジェクト上の削除演算子の動作は予測不可能です。そして、この動作は実際には間違っていません:(標準により)、ホストオブジェクトは、読み取り(内部[[[get]]メソッド)、write(internal [[put]]メソッド)、削除(内部[[削除]]メソッド)などの複数の演算子に任意の動作を実装できます。このカスタムの恵み[[削除]]動作は、ホストオブジェクトを非常に混乱させるものです。
特定のオブジェクト(ホストオブジェクトとして明らかに実装されている)を削除するためにエラーがスローされるいくつかのIEの癖があります。 Firefoxの一部のバージョンは、window.locationを削除するときにスローします。オペランドがホストオブジェクトである場合、削除の返品値を信頼することはできません。 Firefoxで何が起こるか見てみましょう:
コードコピーは次のとおりです。
/ *「アラート」は「ウィンドウ」の直接プロパティです(「hasownproperty」を信じる場合) */
window.hasownproperty( 'alert'); // 真実
window.alertを削除します。 // 真実
typeof window.alert; // "関数"
Window.Alertは、このプロパティがそのような結果をまったく引き起こす理由がない場合でも、trueを返します。それは参照に解決します(したがって、最初のステップでは真実ではありません)。これは、ウィンドウオブジェクトの直接プロパティです(したがって、2番目のステップでは真実ではありません)。したがって、DeleteがTrueを返すことができる唯一のケースは、4番目のステップに到達し、実際にそのプロパティを削除することです。ただし、このプロパティは削除されません。
この物語の教訓は、ホストオブジェクトを決して信用しないことです。
ES5 STRICTモード:
それで、Strict Mode ECMAScript5は私たちに何をもたらしますか?制限はほとんどありません。削除演算子の式が変数、関数パラメーター、または関数識別子への直接参照である場合、構文エラーがスローされます。さらに、プロパティに内部プロパティがある場合、[[構成]] == false、タイプエラーがスローされます。
コードコピーは次のとおりです。
(function(foo){
「Strictを使用」; //この関数内で厳格モードを有効にします
var bar;
関数baz(){}
fooを削除します。 // syntaxerror(引数を削除するとき)
バーを削除します。 // syntaxerror(変数を削除するとき)
bazを削除します。 // syntaxerror(関数宣言で作成された変数を削除する場合)
/ *関数インスタンスの「長さ」は{[[[configurable]]:false} */
delete(function(){})。length; // typeRror
})();
さらに、未宣言の変数(または未解決の参照)を削除すると、構文エラーもスローします。
「Strictを使用」;
i_dont_exist;を削除します。 // syntaxerror
非宣言されていない割り当ては、厳密なモードで非宣言されていない変数と同様に動作します(今回は、構文エラーの代わりに見積エラーが発生します):
「Strictを使用」;
i_dont_exist = 1; //参照エラー
あなたが今理解しているように、すべての制限は多かれ少なかれ意味があります。なぜなら、変数、関数宣言、およびパラメーターの削除は非常に多くの混乱を引き起こす可能性があるからです。削除操作を静かに無視する代わりに、厳密なパターンはより根本的で記述的な尺度をとります。
要約:
このブログ投稿は非常に長くなっていたので、deleteを使用して配列オブジェクトを削除するなどのことやその意味について話すつもりはありません。 MDCの記事の特別な説明を参照できます(または、標準を読んで、独自の実験を行うことができます)。
JavaScriptで削除操作がどのように機能するかについての簡単な要約を次に示します。
変数と関数宣言は、アクティブオブジェクトまたはグローバルオブジェクトのプロパティです
属性にはいくつかの特性があり、dontdeleteは、この属性を削除できるかどうかを決定する属性です。
グローバルまたは関数コードの変数と関数宣言は、常にDontDelete属性を使用して属性を作成します。
関数パラメーターは常にアクティブオブジェクトの属性であり、dontdeleteが伴います。
評価コードで宣言された変数と関数は、常にDontDeleteなしでプロパティを作成します。
新しいプロパティには、作成されたときに属性がありません(もちろん、DontDeleteもありません)。
ホストオブジェクトは、削除操作にどのように反応するか独自に決定できます。
ここで説明されていることにもっと精通したい場合は、ECMA-262第3版仕様を参照してください。
この記事を楽しんで、何か新しいことを学ぶことができることを願っています。質問、提案、または修正は大歓迎です。