4

私はまだwithキーワードを少し見つけます...謎めいた.

簡単に言えば、次のようにwith動作します。

with (obj) {
    // do stuff
}

objこれはスコープ チェーンの先頭に追加され、with-block が実行されます。objブロックが終了すると、スコープ チェーンの先頭から削除されます。

MDCによると、これにより次のようなことが可能になります

var a, x;
var r = 10;
with(Math) {
    a = PI * r * r;
    x = r * cos(PI / 2);
}

だから、言うまでもなくMath-- like PI-- のプロパティを直接参照できますMath.PI。これは問題ありませんが、役に立たないものです。

の興味深い使用例を誰か教えてwithください。

4

6 に答える 6

5

for ループ内で関数を使用する標準的なクロージャー ソリューションの代替:

<a  href="#">blah</a><br>
<a  href="#">blah</a><br>
<a  href="#">foo</a><br>
<script>
    (function() {
    var anchors = document.getElementsByTagName('a');
        for ( var i = anchors.length; i--; ) {
            var link = anchors[i];
            with ({ number: i }) {
                link.onclick = function() {
                    alert(number);
                };
            }
        }
    })();
</script>

nlogax私がかなり食い物にしたソリューションを提供してくれた 功績: Javascriptの悪名高いループの問題?

標準的な解決策は次のとおりです。

<script>
    (function() {
    var anchors = document.getElementsByTagName('a');
    for ( var i = anchors.length; i--; ) {
        var link = anchors[i];
        (function(i) {
            link.onclick = function() {
                alert(i)
            }
        })(i);
    }
    })();
</script>
于 2009-11-04T19:27:35.263 に答える
4

withここで、 JavaScriptのステートメントは広く非推奨になっていると言わなければなりません。

ダグラス・クロックフォードの「有害と考えられるステートメント」を参照してください。

私は彼がしたよりもそれを言うことはできません(真剣に、リンクをたどってください)、しかしあなたがこれをするならば、要するに:

with (mySuperLongObjectReferenceThatIHateTyping) {
  propertyAlpha = 'a';
  propertyBeta = 2;
  propertyGamma = false;
}

mySuperLongObjectReferenceThatIHateTypingオブジェクトまたはグローバルオブジェクト(ウィンドウ)のプロパティに値を割り当てているかどうかは、そのコードを見てもわかりません。

Crockfordはこれを推奨しています:

var o = mySuperLongObjectReferenceThatIHateTyping;
o.propertyAlpha = 'a';
o.propertyBeta = 2;
o.propertyGamma = false;

これは明白です。または、関数を使用してスコープを設定し、別のグローバル変数を作成しないようにすることもできます。

(function(o) {
  o.propertyAlpha = 'a';
  o.propertyBeta = 2;
  o.propertyGamma = false;
})(mySuperLongObjectReferenceThatIHateTyping);
于 2009-11-04T19:35:18.383 に答える
3

John Resigのjavascriptマイクロテンプレートは、withの興味深い使用法を示しています。

于 2009-11-04T19:41:17.943 に答える
2

style私は定期的にそれを使用して、オブジェクトに複数のCSSプロパティを追加します。

with(document.body.style) {
    color = 'green';
    background = 'red';
}

また、オブジェクト自体への参照を格納することなく、オブジェクトのプロパティをローカル変数に割り当てるために少なくとも1回は使用しました。

これは、変数の値の「スナップショット」を取得する場合のクロージャの代替手段でもあります。

var foo = [];
for(var i = 10; i--;)
    with({ i : i }) foo[i] = function() { document.writeln(i); };

// prints 0..9
for(var i = 0; i < foo.length; ++i)
    foo[i]();

with変数名を解決するときは、字句環境に追加したオブジェクトのプロトタイプチェーンを最初にチェックする必要があるため、パフォーマンスに深刻な影響を与える可能性があることに注意してください。

于 2009-11-04T19:39:55.377 に答える
1

JSのwithステートメントは、たとえばVB.netのwithステートメントに似ています。これは、オブジェクトのプロパティ/メソッドとの繰り返しを回避するための単なる方法です。

たとえば、ラベルコントロールがイベント/アクションに基づいて変更されていると仮定します。そのラベルコントロールには、FontColor、CSSClass、Visibilityなどのプロパティがあります。

プログラマーが書く代わりに:

myLabel.FontColor=Color.Blue
myLabel.CSSClass="SomeCSSClass"
myLabel.Visiblity=True
myLabel.Text = "Hello World"

これを次のように短縮できます。

With myLabel
  .Text = "Hello World"
  .FontColor = Color.Blue
  .CssClass="SomeCSSClass"
  .Visibility=True
End With
于 2009-11-04T19:26:24.437 に答える
1

私は Javascript の経験がなく、それをどのように使用すべきかを理解し始めたばかりなので、私の意見は、特定の言語の経験がある人の意見と同じ重みを持つべきではありません。私は自分の考えに対する反応に興味があります。

私は、JavaScript のwithステートメントに依存するクラスのようなオブジェクトを定義するスタイルを試してきました。私はこれが正当な使用であることを提出します。

このスタイルの各クラスのようなオブジェクトは、オブジェクトが何らかの目的を満たすためのファクトリとして機能します。

このスタイルは、インスタンス メソッドでthisキーワードを使用しません。

このスタイルは、これらのクラスのようなオブジェクトの 1 つから生成された各オブジェクトがパブリックな側面とプライベートな側面を持つことを想定しています。JavaScript オブジェクトは、これらの各側面を表します。オブジェクトへの参照の保持者は、実際にはパブリック アスペクトのみを参照します。ただし、メソッドは両方の側面を認識しており、クロージャーを使用してこれを実装しています。

このスタイルが、実行時間やメモリ パフォーマンスを重視する場合に適用できるとは思いません。私は、プログラミングの効率化のために、これらのそれぞれのかなりの部分を意図的に犠牲にしています。何かをすばやくプログラムし、エラーの可能性をほとんどなくしたい場合や、実行時の要求が重要ではない場合がたくさんあると思います。

私は node.js ではなくブラウザーでコードを試してきたので、開発環境に関する実際的な考慮事項は、大きなソース ファイルの構文エラーを突き止めて修正するのが難しいということです。コードを少しずつ追加することで、この問題に対処しています。したがって、すべてのメソッド定義を 1 つのソース ファイルに記述する必要はなく、クラスに似たオブジェクトが一度にインスタンス メソッド定義を受け入れることができるようにする必要があります。

最初にインスタンス メソッドを定義せずにクラスのようなオブジェクトを宣言し、そのクラスのようなオブジェクトをプログラミングしている名前空間に配置します。

次に、「init」と呼ばれるメソッドでクラスのようなオブジェクトを繰り返し呼び出し、そのたびに、インスタンスの初期化中に呼び出される関数であるinitializerを渡します。

最終的に、クラスのようなオブジェクトをそのインスタンスのファクトリとして使用し始めると、新しいインスタンスを要求するたびに、インスタンスのパブリック アスペクトとプライベート アスペクトが作成され、プライベート アスペクトがパブリック アスペクトにリンクされ、すべての定義されたイニシャライザに、新しいインスタンスのプライベートな側面を渡します。

私のスタイルでは、すべてのパブリック属性はメソッドです。値が関数にならないすべての変数は、プライベート側に存在する必要があります。

初期化子ができることの 1 つは、プライベート側で変数を確立することです。

イニシャライザができるもう 1 つのことは、パブリック側またはプライベート側にメソッドを追加することです。

初期化子を実行する順序は重要です。クラスのようなオブジェクトは、定義されているのと同じ順序で実行する必要があります。したがって、各イニシャライザは、以前のイニシャライザによって確立された属性を持つインスタンスのパブリックおよびプライベートの側面を当てにすることができます。プログラマーにとって、これは事実上一対のレキシカル スコープを作成します。これは、初期化子が条件付きコードまたは動的コードによって確立されないためです。それらは、ソースファイルがブラウザによって読み取られて解析された直後に実行されるときに確立されます。

一部の言語、特に Ruby 言語と Self 言語では、ネイキッド識別子を記述し、それを現在のオブジェクトのメソッド呼び出しとして解釈させることができます。したがって、Ruby では「foo」は「self.foo」を意味し、Self では「foo」は「self foo」を意味します (メソッド呼び出しの構文はこれらの言語間で異なりますが、私が話している詳細レベルまでは異なります)。 Ruby の「self.foo」と Self の「self foo」は同じです)。この「self」の省略形は、プライベート メソッドやインスタンス変数を呼び出す場合に特に便利です。Javascript 言語は、この便利さを提供しません。

値にプライベートまたはパブリック側の属性を使用したいインスタンス メソッド内のコンテキスト (割り当ての左側ではないことに注意してください) では、名前だけで属性を参照できる便利さが気に入っています。 「vars」と書く必要はありません。または「自分」。それを見つけるためにその左側にあります(私はプライベートアスペクトに「vars」を使用し、パブリックアスペクトに「self」を使用します)。このため、各イニシャライザを Javascriptでラップします。声明。私のスタイルでは、対象となるオブジェクトの人口は語彙的に確立されているため、これは私には正当に思えます。属性を確認するには、プログラマーはソース ファイルで以前に提供された同じクラスのようなオブジェクト (ソース コードでは名前で識別されるため、ソフトウェア エンジニアリングの目的で、 Javascript パーサーはこれを検出しませんが、語彙エンティティ)。

于 2012-04-14T20:15:32.567 に答える