10

Chrome では、コンソールで次のことを試してください。初め

console = 0;

0に値を割り当てますconsole。それで

console // (prints `0`)

正しく上書きされたことを確認しますconsole。ついに、

delete console

驚くべきことに、元のオブジェクトconsoleを保持するようになりました。Console事実上、それを根絶するのではなく、deleteキーワード「復活」console

これは予想される動作ですか?これは Chromium コードのどこに実装されていますか?

4

8 に答える 8

12

MDN のドキュメントにdelete記載されているように:

delete 演算子が成功すると、オブジェクトからプロパティが完全に削除されますが、オブジェクトのプロトタイプで同様の名前のプロパティが明らかになる可能性があります。

プロトタイプdeleteチェーンを介して継承されたネイティブ プロパティのシャドウを単純に解除します。

一部のブラウザーはwindowネイティブ プロトタイプから継承しており、詳細を本当に知りたい場合は、ソースをチェックアウトしてプロパティがどのように継承されているかを確認する必要がありますが、ほとんどの場合、それらは JS のものと同じように機能します。

于 2012-09-03T14:05:57.733 に答える
3

とった:

コンソールがグローバルオブジェクトのプロパティであることを証明できました。コンソールを開いて、次のように入力します。this.parentまたはwindow.parent。これにより、自由に使用できるプロパティとメソッドのより完全なリストが表示されます。を含めconsole: Consoleて、そのすぐ下の約2/3 chrome: Object(興味深い... :))。どういうわけかコンソール自体のCSSルールを変更できたことを思い出したときにこれを考えました(クロームでは、どうやってそこにたどり着いたのか聞かないでください、思い出せません)。
結論:consoleこれはウィンドウオブジェクトのプロパティです。これは私の説明をかなりよく裏付けていると思います。


@Randomblue:これがv8でどのように実装されているかに興味があるので、ここでトランクをチェックするか、出血を閲覧することができます。どこかに、を処理する多数のファイルがあるテストディレクトリがありますdelete。グローバル変数/プロパティでの使用には特別な注意が払われてdeleteいます。つまり、削除することはできません。つまり、コンソールが実際になくなることはありません。なぜこの答えが役に立ったと投票されて受け入れられたのか、役に立たなかったのか受け入れられなかったのか知りたいのですが...


それは完全に簡単です。Consoleランダムなスタンドアロンのオブジェクトではありません。これは実際にはグローバルオブジェクトのプロパティです。コンソールを開き、またはと入力しthis.console === consoleますwindow.console === console。もちろん、それは真実を記録します。

したがって、暗黙のグローバルのおかげでconsole = 0、とほとんど同じwindow.console = 0です。インスタンスのプロパティを再割り当てしているようなものです。通常のオブジェクトとの違いは、グローバルオブジェクトが単なる古いオブジェクトではないことです。そのプロパティは削除できません(ここではMDNのどこかにあります)。つまり、グローバルはまだ存在しているコンソールオブジェクトをマスクしているので、参照も失われています。

var bar = window.console;
console = 12;
bar.log(console);//logs 12, bar is now an alternative reference to the console object
delete console;//unmasks the console reference
console === bar;//true

しばらくの間、グローバルオブジェクトにプロトタイプがないことに騙されないでください。入力this.constructor.nameして見よWindow、大文字Wで表示されます。ダブルチェックの別の方法は次のとおりです。Object.getPrototypeOf(this);またはObject.getPrototypeOf(window);。言い換えれば、考慮すべきプロトタイプがあります。いつものように、チェーンは:で終わりObject.prototypeます

 Object.getPrototypeOf(Object.getPrototypeOf(window));

要するに、ここでは奇妙なことは何も起こっていませんが、グローバルオブジェクト自体の奇妙な性質があります。ある種のプロトタイプの継承が行われているように動作します。次のように設定されているかのように、グローバルオブジェクトを確認します。

this.prototype.window = this;//<-- window is a circular reference, global obj has no name
this.prototype.console = new Console();//this is the global object
this.hasOwnProperty(console);//false
console = 0;//implied global

アクセスしようとするとconsole、JSはオブジェクトconsoleのインスタンスの前に設定したプロパティを見つけ、Consoleその値を喜んで返します。それを削除しても同じことが起こり、最初に出現したものconsoleは削除されますが、プロトタイプチェーンの上位のプロパティは変更されません。次回consoleリクエストされると、JSは継承チェーンをスキャンし、古いコンソールインスタンスを返します。console-objectが実際になくなることはなく、自分で設定したプロパティの背後に隠されているだけです。

トピックから外れていますが、完全を期すために:
グローバルオブジェクトの特殊文字のために、これよりもいくつかのことがあります(オブジェクト/プロトタイプチェーン検索の前のスコープスキャン)が、これはAFAIK、の本質ですそれ。
あなたが知る必要があるのは、(少なくとも)1つのプロトタイプがなければ、オブジェクトのようなものは(JSでは)存在しないということです。これにはグローバルオブジェクトが含まれます。あなたがしていることは、現在のグローバルオブジェクトのインスタンスを拡張し、プロパティを削除するだけで、プロトタイプが再び引き継ぎます。そのような単純な。@Peeterが彼の答えでほのめかしたのは、それです。暗黙のグローバルは、グローバルオブジェクトを変更するため、厳密モードでは許可されません。私がここで説明しようとしたように、これはまさにここで起こることです。

于 2012-09-10T09:12:12.813 に答える
2

まず、これは単なるコンソールではありません。すべてのネイティブプロパティ上のすべてのブラウザ定義プロパティwindow

setTimeout = 0;
setTimeout //=> 0
delete window.setTimeout;
setTimeout //=> function setTimeout() { [native code] }

ECMA スクリプト仕様の一部であるプロパティは、完全に上書きおよび削除できます。

Array = 0;
Array //=> 0
delete window.Array;
Array //=> ReferenceError

上の任意のプロパティをほぼ上書きしwindow、上書きを削除して通常の機能に戻すことができます。

これの単純な理由は、コンソールと他のすべてのネイティブ グローバル関数ブラウザーで定義されたプロパティは、javascript ではなくC++ を介して DOMWindow オブジェクトにリンクされます。ここでDOMWindow に接続されているコンソールと、ここで DOMWindowの実装を確認できます。

ということでもありますwindow オブジェクトは、javascript オブジェクトとしてマスクされた C++ オブジェクトです。window オブジェクトは少なくとも部分的に C++ によって定義されており、魔法のように機能するプロトタイプの継承ではありません。例を次に示します。

window.hasOwnProperty('console') //=> true, console is defined directly on the window
window.__proto__.hasOwnProperty('console') // => false, the window prototype does not have a console property

また、それがプロトタイプの継承である場合、以下はコンソールが 3 を返すことにつながります。

window.__proto__.console = 3;
delete console;
console //=> still returns console;
window.hasOwnProperty('console') //=> the window still has it.

プロトタイプの継承に関するプロパティと同じです。

window.someProp = 4;
window.__proto__.someProp = 6;
someProp //=> 4
delete someProp;
someProp //=> 6

したがって、console何かに設定すると、それはなくなり、(皮肉なことに万歳)によってのみ復活できますdelete console

つまり、ウィンドウ オブジェクトのネイティブ プロパティを削除することはできません。上書きされていないときに試してみてください。もう一度delete window.consoleポップアップするだけです。そもそも(厳格モードであっても)警告を受け取ることなく(私の目には)上書きできるという事実は、javascriptの主要な脆弱性の1つです(ほぼすべてのページでsetTimeoutを0に設定すると、破れるのがわかりますそれ自体は別ですが、スパイダーマンで彼らが言うように:

大きな力には大きな責任が伴う

アップデート

これがブラウザ/エンジンの実装に固有のものであり、言語自体の要件ではないというヒントを含めるには:

delete this.console //=> true
console //=> ReferenceError

delete parseInt //=> true
parseInt //=> ReferenceError
于 2012-09-11T15:06:50.830 に答える
2

ウィンドウ オブジェクトの一部のプロパティは削除できません。厳密モードで実行していないため、True が返されます。以下を試してください(コンソールではありません):

"use strict";
delete console;

例外が発生します ( JSFiddle )。

これがどのように処理されるかについて詳しくは、http://es5.github.com/#x11.4.1をご覧ください。

于 2012-09-01T00:36:38.347 に答える
0

まったく同じことが Firefox でも起こります。

私自身の観察に基づいて、次のように仮定しています。

変数は最初にローカル変数と一致するかどうかがチェックされ、そうでない場合は、それらが一致するかどうかがチェックされますwindow.variable

1 に設定consoleすると、ローカル変数consoleが 1 に設定されるため、ルックアップではwindow.console(まだ存在する) の代わりにそれが表示されます。delete consoleローカル変数がconsole削除されると。これで、 のすべてのルックアップconsoleが一致しwindow.consoleます。それがあなたが得る行動を得る理由です。

これは、Firefox で JavaScript インタープリターを試したことに基づいていると思います。また、用語が間違っていて申し訳ありません (自由に編集してください)。私は名前空間の経験があまりありません。

于 2012-09-01T00:38:58.153 に答える
0

delete 演算子は、オブジェクトからプロパティを削除します。

...

delete 演算子を使用して、暗黙的に宣言された変数を削除できますが、var または function ステートメントで宣言された変数は削除できません。

MDN で見るdelete

編集:

本当に筋金入りの JavaScript に興味がある場合は、deleteについても参照してください。

于 2012-09-01T00:46:34.650 に答える
-1

何が起こるかというと、オブジェクトのプロトタイプを上書きしてから、上書きされた値を削除すると、残っているのは元のオブジェクト、つまりプロトタイプです。

于 2012-09-13T13:51:24.690 に答える
-2

予想される行動。Javascript コンソールがブラウザーのグローバル空間で実行されるのではなく、独自の匿名関数内で実行されるという事実はほとんど知られていません。

ブラウザによって処理が異なることは知っていますが、要するに、delete はグローバル空間で動作していないため、期待どおりに動作しません。

本当に物事が壊れるのを見たい場合は、で遊んでみてくださいdelete window.console

わかりました、それは公式です - 私はばかです。ECMAScript の新機能の 1 つは、プロパティを として宣言する機能ですdontdelete。その混乱について申し訳ありません。

于 2012-09-01T00:33:22.937 に答える