ホームページ >ウェブフロントエンド >jsチュートリアル >Javascript_javascript スキルでの削除の概要

Javascript_javascript スキルでの削除の概要

WBOY
WBOYオリジナル
2016-05-16 17:50:241165ブラウズ
1. 質問の提起

まず次のコードを見てみましょう。次のコードはブラウザの開発者ツール (FireBug など) では使用しないでください。 、Chrome デベロッパー ツール) を実行します。その理由は後で説明します:

オブジェクトの属性を削除できる理由:
コードをコピーします コードは次のとおりです:

var o = { x: 1 };
delete o.x; // true
o.x;

ただし、次のように宣言された変数のように削除することはできません:
コードをコピー コードは次のとおりです:

var x = 1;
delete x; // 1

次のように定義された関数も削除できません。 >

function x(){}
delete x ; // false
typeof x; // "function"


注: 削除演算子が true を返す場合は削除できることを意味し、false を返す場合は削除できないことを意味します

これを理解するには、まず変数のインスタンス化や属性の特性などの概念を習得する必要があります。 -残念ながら、これらの内容は一部の JavaScript 書籍ではほとんど言及されていません。これらを理解するのは難しいことではありません。なぜそのように動作するのかが気にならない場合は、この部分をスキップしても問題ありません。


2. コードの種類
ECMAScript の実行コードには、グローバルコード (global code)、Function コード (関数コード)、Eval コード ( code) の 3 種類があります。 Eval で実行されます)。


var x=1;//グローバル コード
function test(){
var y=2;//関数コード
eval("var z=3");//関数内の評価コード
}
eval("function evalTest() {}");//グローバルの評価コード



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

ご覧のとおり、実行コンテキストは論理的にスタックから取得されます。まず、コードは独自のスコープを持つ関数を呼び出すことができ、その関数は別の関数を呼び出すことができます。関数がそれ自体を再帰的に呼び出す場合でも、各呼び出しは新しい実行コンテキストに入ります。


4. アクティベーション オブジェクト/変数オブジェクト

各実行コンテキストには、内部に変数オブジェクトがあります。実行コンテキストと同様に、Variable オブジェクトは、変数のインスタンス化のメカニズムを記述するために使用される抽象エンティティです。興味深いのは、コード内で宣言された変数と関数が、実際にはこの変数オブジェクトのプロパティとして追加されることです。
グローバルコードの実行コンテキストに入るとき、グローバルオブジェクトは変数オブジェクトとして使用されます。これが、グローバル スコープで宣言された変数または関数がグローバル オブジェクトのプロパティになる理由です。


/* `this` が参照していることを覚えておいてください。グローバル スコープ内のグローバル オブジェクト */
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');




単に宣言されていない代入は、グローバル オブジェクトのプロパティに削除可能なオブジェクトを作成します。


コードをコピーします


コードは次のとおりです。
var GLOBAL_OBJECT = this; 🎜>/ * 変数宣言を介してグローバル プロパティを作成; プロパティに DontDelete がある */ var foo = 1; /* 宣言されていない代入を介してグローバル プロパティを作成; プロパティに DontDelete がありません */ bar = 2;/ / window.bar=2; と理解できます。上記の 5 番目の点に従って、削除できます。
delete foo; // false
typeof foo; >
delete bar; // true
typeof bar; // "unknown"


DontDelete 属性はプロパティの作成プロセス中に決定され、その後の割り当ては変更されないことに注意してください。存在の性質を理解することが重要です。




コードをコピー


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


/* `foo` はDontDelete を使用したプロパティ */
function foo(){} /* DontDelete はまだ存在します。 */ foo = 1; / false typeof foo; // "number" /* ただし、存在しないプロパティに代入すると、
そのプロパティが空の属性で作成されます (したがって 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); //未定義
関数 y(){ var z=1; console.log(delete z);//false } y(); delete y; console.log(typeof y);//未定義

これは明らかに上記のルールに反しますが、上記の 8 番目の点と比較すると、これはeval で実行されるコードの影響。未確認ですが、おそらくFireBug(Chrome開発者ツール)のコンソールコードはevalを使って実行されていると思われます。

したがって、JS コードをテストするときは、現在のコンテキストが含まれる場合は特に注意する必要があります。


10. delete 演算子によって削除されるオブジェクト


C には、ポインタが指すオブジェクトを削除する delete 演算子もあります。例:




コードをコピー


コードは次のとおりです。
class Object {
public :
Object *x;
}
Object o; o.x = new Object(); // 前のオブジェクトの新しいオブジェクトLINEがリリースされます
しかし、JavaScript の削除は C とは異なります。o.x が指すオブジェクトを削除するのではなく、o.x 属性自体を削除します。
コードをコピーします コードは次のとおりです。

var o = {}; o.x = new Object();
delete o.x; // 前の行の新しい Object オブジェクトはまだ存在します
o.x; // o の x という名前の属性は削除されます

実際の Javascript では、o.x を削除した後、Object オブジェクトは参照を失ったためガベージ コレクションされます。そのため、o.x を削除することは、o.x が指すオブジェクトを削除することと「同等」ですが、このアクションは ECMAScript の標準ではありません。つまり、実装が Object オブジェクトをまったく削除しない場合でも、ECMAScript 標準には違反しません。

「オブジェクトの削除ではなく属性の削除」は以下のコードで確認できます。

コードをコピーします コードは次のとおりです。
var o = {}; var a = { x: 10 };
o.a = a;
delete o.a; // o.a 属性は削除されます。
a.x; : 10 } オブジェクトは残ります a によって参照されるため、再利用されません


また、delete o.x は delete o["x"] と書くこともできます。どちらも同じです。効果。

11. 削除できないその他の属性

削除できない上記の組み込み属性 (つまり、事前定義された属性) に加えて、プロトタイプ 削除できません:


コードをコピー コードは次のとおりです: function C () { this.x = 42; }
C.prototype.x = 12;

var o = new C(); ; // 42, 関数で定義された o.x

delete o.x; // true はそれ自体で定義された x を削除します
o.x; // 12, delete してもプロトタイプで定義された o.x は削除されませんo.x が再度実行される

delete o.y; //o 自体には o.y 属性がなく、y はプロトタイプ チェーンに存在するため、オブジェクト自身の属性とプロトタイプの属性は異なることを意味します
o.y; //13



概要

ここまで述べてきましたが、JavaScript での削除を理解するのに役立つことを願っています。レベルが限られているため、完全に正しいという保証はありません。誤りを見つけた場合は修正してください。

原文は、
1.
http://perfectionkills.com/ Understanding-delete/
(英語)
2.
http://nanto .asablo .jp/blog/2008/01/09/2552470
(日本語) この記事は http://jscode.cnblogs.com で最初に公開されました。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。