まず次のコードを見てみましょう。次のコードはブラウザの開発者ツール (FireBug など) では使用しないでください。 、Chrome デベロッパー ツール) を実行します。その理由は後で説明します:
これを理解するには、まず変数のインスタンス化や属性の特性などの概念を習得する必要があります。 -残念ながら、これらの内容は一部の JavaScript 書籍ではほとんど言及されていません。これらを理解するのは難しいことではありません。なぜそのように動作するのかが気にならない場合は、この部分をスキップしても問題ありません。
2. コードの種類
ECMAScript の実行コードには、グローバルコード (global code)、Function コード (関数コード)、Eval コード ( code) の 3 種類があります。 Eval で実行されます)。
3. 実行コンテキスト
ECMAScript コードが実行されると、は常に特定の実行コンテキスト内にあり、スコープと変数のインスタンス化がどのように機能するかを理解するのに役立つやや抽象的なエンティティです。 3 種類の実行可能コードのそれぞれに、実行コンテキストがあります。関数が実行されると、制御は関数コードの実行コンテキストに入ると言うことになります。グローバル コードが実行されると、グローバル コードの実行コンテキスト (グローバル コード) に入ります。
ご覧のとおり、実行コンテキストは論理的にスタックから取得されます。まず、コードは独自のスコープを持つ関数を呼び出すことができ、その関数は別の関数を呼び出すことができます。関数がそれ自体を再帰的に呼び出す場合でも、各呼び出しは新しい実行コンテキストに入ります。
4. アクティベーション オブジェクト/変数オブジェクト
グローバルコードの実行コンテキストに入るとき、グローバルオブジェクトは変数オブジェクトとして使用されます。これが、グローバル スコープで宣言された変数または関数がグローバル オブジェクトのプロパティになる理由です。
var GLOBAL_OBJECT = this;
GLOBAL_OBJECT.foo; // 1
foo === GLOBAL_OBJECT.foo; true
function bar(){}
typeof GLOBAL_OBJECT.bar; // "関数"
GLOBAL_OBJECT.bar === bar; // true
グローバル変数はグローバル オブジェクトのプロパティになりますが、関数コードで定義されたローカル変数はどうなるでしょうか?実際の動作は非常に似ており、変数オブジェクトのプロパティになります。唯一の違いは、関数コードでは変数オブジェクトがグローバル オブジェクトではなく、いわゆるアクティベーション オブジェクトであることです。関数コードが実行スコープに入るたびに、アクティベーション オブジェクトが作成されます。
関数コード内の変数や関数だけでなく、関数の各パラメーター (仮パラメーターに対応する名前) や特定の Arguments オブジェクトもアクティベーション オブジェクトのプロパティになります。アクティベーション オブジェクトは内部メカニズムであり、実際にはプログラム コードによってアクセスされないことに注意してください。
(function(foo){
var bar = 2;
function baz(){}
/*
抽象的に言えば、
特別な `arguments` オブジェクトは、関数の Activation を含むプロパティになります。 object:
ACTIVATION_OBJECT.arguments; // 引数オブジェクト
... および引数 `foo`:
ACTIVATION_OBJECT.foo; // 1
...として変数 `bar`:
ACTIVATION_OBJECT.bar; // 2
...ローカルで宣言された関数:
typeof ACTIVATION_OBJECT.baz; // "function"
* /
})(1);
最後に、Eval コードで宣言された変数が、呼び出し元コンテキストの変数オブジェクトのプロパティとして作成されます。 Eval コードは、それが呼び出される実行コンテキストの変数オブジェクトのみを使用します。
var GLOBAL_OBJECT = this; 🎜>/ * `foo` は呼び出しコンテキスト変数オブジェクトのプロパティとして作成されます。
この場合は Global オブジェクトです */
eval('var foo = 1;'); >GLOBAL_OBJECT. foo; // 1
(function(){
/* `bar` は呼び出しコンテキスト変数オブジェクトのプロパティとして作成されます。この場合は、含まれる関数のアクティブ化オブジェクト */
eval('var bar = 1;');
/*
抽象的には、
ACTIVATION_OBJECT.bar; 🎜>* /
})();
変数に何が起こるかは明らかです (次のようになります)属性)、そして残る唯一のものは、理解する必要がある概念です。各属性には、次の属性セット (ReadOnly、DontEnum、DontDelete、および Internal) からの 0 個以上の属性があります。これらは、オプションの属性であるタグと考えることができます。今日の説明では、DontDelete 属性のみに注目します。
宣言された変数と関数が変数オブジェクト (アクティベーション オブジェクト (関数コード) またはグローバル オブジェクト (グローバル コード) のいずれか) のプロパティになると、これらの作成されたプロパティは DontDelete 属性を持ちます。ただし、明示的に (または暗黙的に) 作成されたプロパティには DontDelete 属性がありません。このため、一部のプロパティは削除でき、一部のプロパティは削除できません。
コードをコピーします
コードは次のとおりです。
/* `bar` は Global オブジェクトのプロパティです。
関数宣言を介して、DontDelete 属性も削除できません。 */
function bar(){}
delete bar; // false
typeof bar; ; // "function"
/* `baz` も Global オブジェクトのプロパティです。
ただし、プロパティの割り当てによって作成されるため、DontDelete 属性がありません。
これが理由です。 */
GLOBAL_OBJECT.baz = 'blah';
delete GLOBAL_OBJECT.baz; // "未定義"
6. 組み込み属性と DontDelete
一言で言えば、属性内の固有の特性 (DontDelete) によって、この属性を削除できるかどうかが制御されます。オブジェクトの組み込みプロパティ (つまり、オブジェクトの事前定義されたプロパティ) には DontDelete 属性があるため、削除できないことに注意してください。具体的には、Arguments 変数 (または、現在ではアクティベーション オブジェクトのプロパティ)、関数インスタンスの length プロパティにも DontDelete 属性があります。
コードをコピー
コードは次のとおりです:
(function(){
/* DontDelete があるため、`arguments` は削除できません */
delete argument; // false
引数の種類; // "オブジェクト"
/* 関数の `length` は削除できません; DontDelete もあります */
function f(){}
delete f.length; / false
typeof f.length; // "number"
})();
関数のパラメータに対応して作成されたプロパティにも DontDelete 属性があります。また、削除することもできません。
(function(foo, bar){
delete foo; // false
foo; // false
bar; 1, ' blah');
単に宣言されていない代入は、グローバル オブジェクトのプロパティに削除可能なオブジェクトを作成します。
コードをコピーします
コードは次のとおりです。
delete foo; // false
typeof foo; >
delete bar; // true
typeof bar; // "unknown"
DontDelete 属性はプロパティの作成プロセス中に決定され、その後の割り当ては変更されないことに注意してください。存在の性質を理解することが重要です。
コードをコピー
コードは次のとおりです:
/* `foo` はDontDelete を使用したプロパティ */
そのプロパティが空の属性で作成されます (したがって DontDelete は使用されません) */
this.bar = 1;
delete bar; // true
typeof bar;
8.
Eval で作成された変数またはメソッドは特別であり、DontDelete 属性を持ちません。つまり、削除できることを意味します。
コードをコピー
コードは次のとおりです。
eval("var x = 1;" );
console.log(x); // 1
delete x;
ここで Eval で作成する変数やメソッドには、上記の赤い部分など、メソッド内の変数やメソッドは含まれないことに注意してください。コードはまだ削除できません。前に述べたことと同じです。
9. FireBug に関する混乱
FireBug で実行されたコードの結果を見てみましょう:
コードをコピー
コードは次のとおりです:
var x=1;
delete x;
console.log(typeof x); //未定義
これは明らかに上記のルールに反しますが、上記の 8 番目の点と比較すると、これはeval で実行されるコードの影響。未確認ですが、おそらくFireBug(Chrome開発者ツール)のコンソールコードはevalを使って実行されていると思われます。
したがって、JS コードをテストするときは、現在のコンテキストが含まれる場合は特に注意する必要があります。
10. delete 演算子によって削除されるオブジェクト
C には、ポインタが指すオブジェクトを削除する delete 演算子もあります。例:
コードをコピー
コードは次のとおりです。
class Object {
public :
Object *x;
}