383

with声明に関する私の回答に対するAlan Storm のコメントは、私に考えさせました。この特定の言語機能を使用する理由を見つけることはめったにありませんでしたし、それがどのように問題を引き起こす可能性があるかについてもあまり考えたことがありませんでした. withさて、落とし穴を避けながら を効果的に利用するにはどうすればよいか、興味があります。

withこのステートメントはどこで役に立ちましたか?

4

32 に答える 32

531

今日、別の使用法が発生したので、私は興奮してWebを検索し、その既存の言及を見つけました:ブロックスコープ内の変数の定義

バックグラウンド

JavaScriptは、CおよびC ++に表面的に類似しているにもかかわらず、変数を次のように定義されているブロックにスコープしません。

var name = "Joe";
if ( true )
{
   var name = "Jack";
}
// name now contains "Jack"

ループ内でクロージャを宣言することは、これがエラーにつながる可能性がある一般的なタスクです。

for (var i=0; i<3; ++i)
{
   var num = i;
   setTimeout(function() { alert(num); }, 10);
}

forループは新しいスコープを導入しないため、同じnum(値が2)が3つの関数すべてで共有されます。

新しいスコープ:letおよびwith

ES6letにステートメントが導入されると、これらの問題を回避するために、必要に応じて新しいスコープを簡単に導入できるようになります。

// variables introduced in this statement 
// are scoped to each iteration of the loop
for (let i=0; i<3; ++i)
{
   setTimeout(function() { alert(i); }, 10);
}

あるいは:

for (var i=0; i<3; ++i)
{
   // variables introduced in this statement 
   // are scoped to the block containing it.
   let num = i;
   setTimeout(function() { alert(num); }, 10);
}

ES6が広く利用可能になるまで、この使用は、トランスパイラーを使用することをいとわない最新のブラウザーと開発者に限定されたままです。ただし、次を使用してこの動作を簡単にシミュレートできますwith

for (var i=0; i<3; ++i)
{
   // object members introduced in this statement 
   // are scoped to the block following it.
   with ({num: i})
   {
      setTimeout(function() { alert(num); }, 10);
   }
}

ループは意図したとおりに機能し、0〜2の値を持つ3つの個別の変数を作成します。C++でのブロックの動作とは異なり、ブロック内で宣言された変数はスコープされないことに注意してください(Cでは、変数はブロックなので、ある意味で似ています)。この動作は、実際には以前のバージョンのMozillaブラウザで導入されたletブロック構文と非常に似ていますが、他の場所では広く採用されていません。

于 2008-10-08T23:05:02.273 に答える
164

私はスコープ付きインポートの単純な形式として with ステートメントを使用してきました。ある種のマークアップビルダーがあるとしましょう。書くのではなく:

markupbuilder.div(
  markupbuilder.p('Hi! I am a paragraph!',
    markupbuilder.span('I am a span inside a paragraph')
  )
)

代わりに次のように書くこともできます:

with(markupbuilder){
  div(
    p('Hi! I am a paragraph!',
      span('I am a span inside a paragraph')
    )
  )
}

このユースケースでは、割り当てを行っていないため、それに関連するあいまいさの問題はありません。

于 2009-09-22T19:27:03.903 に答える
85

with私の以前のコメントが示したように、どのような状況でどんなに魅力的であっても、安全に使用できるとは思いません. この問題はここでは直接カバーされていないので、繰り返します。次のコードを検討してください

user = {};
someFunctionThatDoesStuffToUser(user);
someOtherFunction(user);

with(user){
    name = 'Bob';
    age  = 20;
}

これらの関数呼び出しを注意深く調査しない限り、このコードの実行後にプログラムの状態がどうなるかを知る方法はありません。user.nameがすでに設定されている場合は、 になりますBob。設定されていない場合、グローバルnameは初期化または変更されBobuserオブジェクトはnameプロパティなしで残ります。

バグが発生します。withを使用すると、最終的にこれが実行され、プログラムが失敗する可能性が高くなります。さらに悪いことに、with ブロックでグローバルを設定する作業コードに遭遇する可能性があります。これは、意図的に、または作成者が構造のこの癖を知らずに行うためです。これは、スイッチでフォール スルーが発生するのとよく似ています。作成者がこれを意図しているかどうかはわかりません。また、コードを「修正」すると回帰が発生するかどうかを知る方法はありません。

現代のプログラミング言語は機能がぎっしり詰まっています。一部の機能は、何年も使用した後、不適切であることが判明したため、使用を避ける必要があります。Javascriptwithもその 1 つです。

于 2008-09-14T21:56:57.143 に答える
71

with最近、このステートメントが非常に役立つことがわかりました。この手法は、現在のプロジェクト (JavaScript で記述されたコマンド ライン コンソール) を開始するまで、まったく思い浮かびませんでした。特別なコマンドをコンソールに入力できる Firebug/WebKit コンソール API をエミュレートしようとしていましたが、それらはグローバル スコープの変数をオーバーライドしません。Shog9の優れた回答へのコメントで言及した問題を克服しようとしたときに、これを考えました。

この効果を実現するために、2 つの with ステートメントを使用して、グローバル スコープの背後にスコープを「階層化」しました。

with (consoleCommands) {
    with (window) {
        eval(expression); 
    }
}

この手法の素晴らしい点は、パフォーマンス上の欠点は別として、withステートメントの通常の懸念に悩まされないことです。なぜなら、とにかくグローバル スコープで評価しているためです。疑似スコープ外の変数が変更されました。

驚いたことに、他の場所で使用されているのと同じ手法を見つけることができたとき、この回答を投稿することに触発されました-Chromiumソースコード!

InjectedScript._evaluateOn = function(evalFunction, object, expression) {
    InjectedScript._ensureCommandLineAPIInstalled();
    // Surround the expression in with statements to inject our command line API so that
    // the window object properties still take more precedent than our API functions.
    expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
    return evalFunction.call(object, expression);
}

編集: Firebug のソースを確認したところ、さらに多くのレイヤーのために4 つのステートメントがチェーン化されています。クレイジー!

const evalScript = "with (__win__.__scope__.vars) { with (__win__.__scope__.api) { with (__win__.__scope__.userVars) { with (__win__) {" +
    "try {" +
        "__win__.__scope__.callback(eval(__win__.__scope__.expr));" +
    "} catch (exc) {" +
        "__win__.__scope__.callback(exc, true);" +
    "}" +
"}}}}";
于 2010-10-20T10:19:49.437 に答える
59

はい、はい、はい。非常に合法的な使用法があります。時計:

with (document.getElementById("blah").style) {
    background = "black";
    color = "blue";
    border = "1px solid green";
}

基本的に、他のDOMまたはCSSフックはwithの素晴らしい使用法です。「CloneNode」が未定義になり、邪魔にならないようにしてそれを可能にすることに決めない限り、グローバルスコープに戻るわけではありません。

Crockfordのスピードの不満は、新しいコンテキストがwithによって作成されることです。コンテキストは一般的に高価です。同意します。しかし、divを作成したばかりで、cssを設定するためのフレームワークが手元になく、15程度のCSSプロパティを手動で設定する必要がある場合、コンテキストの作成は、変数の作成と15の逆参照よりもおそらく安価です。

var element = document.createElement("div"),
    elementStyle = element.style;

elementStyle.fontWeight = "bold";
elementStyle.fontSize = "1.5em";
elementStyle.color = "#55d";
elementStyle.marginLeft = "2px";

等...

于 2009-06-22T18:18:02.883 に答える
35

withあいまいさのない利点を提供する小さなヘルパー関数を定義できます。

var with_ = function (obj, func) { func (obj); };

with_ (object_name_here, function (_)
{
    _.a = "foo";
    _.b = "bar";
});
于 2008-09-14T19:29:13.223 に答える
26

次のことができるので、ほとんど価値がないようです。

var o = incrediblyLongObjectNameThatNoOneWouldUse;
o.name = "Bob";
o.age = "50";
于 2008-09-14T23:57:12.627 に答える
19

私はこれまで使用したことがなく、使用する理由がわかりません。また、お勧めしません。

問題withは、ECMAScript 実装が実行できる多数の字句最適化が妨げられることです。高速な JIT ベースのエンジンの台頭を考えると、この問題はおそらく近い将来さらに重要になるでしょう。

よりクリーンな構成を可能にしているように見えるかもしれませんがwith(たとえば、一般的な無名関数ラッパーの代わりに新しいスコープを導入したり、冗長なエイリアシングを置き換えたりする場合)、 実際には価値がありません。パフォーマンスが低下するだけでなく、間違ったオブジェクトのプロパティに割り当てられたり (注入されたスコープ内のオブジェクトでプロパティが見つからない場合)、おそらく誤ってグローバル変数を導入したりする危険性が常にあります。IIRC、後者の問題は、Crockford が回避を推奨する動機となったものですwith

于 2009-09-23T04:20:04.590 に答える
15

Visual Basic .NET にも同様のWithステートメントがあります。私がこれを使用する最も一般的な方法の 1 つは、多数のプロパティをすばやく設定することです。それ以外の:

someObject.Foo = ''
someObject.Bar = ''
someObject.Baz = ''

、私は書くことができます:

With someObject
    .Foo = ''
    .Bar = ''
    .Baz = ''
End With

これは単なる怠惰の問題ではありません。また、はるかに読みやすいコードになります。.また、JavaScript とは異なり、ステートメントの影響を受けるすべてのものの前に(ドット)を付ける必要があるため、あいまいさに悩まされることはありません。したがって、次の 2 つは明確に区別されます。

With someObject
    .Foo = ''
End With

対。

With someObject
    Foo = ''
End With

前者はsomeObject.Foo; 後者はFoo範囲 someObjectです。

あいまいさのリスクが高すぎるため、JavaScript の区別の欠如により、Visual Basic のバリアントよりもはるかに有用性が低くなることがわかりました。それ以外にも、with読みやすさを向上させる強力なアイデアがあります。

于 2008-09-14T19:09:13.130 に答える
8

この小さなテンプレート エンジンwithで行われているように、オブジェクトの内容をローカル変数としてブロックに導入するために使用できます。

于 2010-09-03T16:19:29.047 に答える
7

使い方はショートカットだと思います。たとえば、オブジェクトを初期化する場合は、「ObjectName」を何度も入力するだけで済みます。Lisp の "with-slots" のようなもので、書くことができます

(with-slots (foo bar) objectname
   "some code that accesses foo and bar"

これは書くことと同じです

"some code that accesses (slot-value objectname 'foo) and (slot-value objectname 'bar)""

言語で「Objectname.foo」が許可されている場合よりも、これがショートカットである理由は明らかですが、それでもなおです。

于 2008-09-14T19:18:31.157 に答える
7

「with」を使用すると、コードをよりドライにすることができます。

次のコードを検討してください。

var photo = document.getElementById('photo');
photo.style.position = 'absolute';
photo.style.left = '10px';
photo.style.top = '10px';

次のように乾燥させることができます。

with(document.getElementById('photo').style) {
  position = 'absolute';
  left = '10px';
  top = '10px';
}

読みやすさと表現力のどちらを好むかによると思います。

最初の例はより読みやすく、おそらくほとんどのコードに推奨されます。しかし、とにかくほとんどのコードはかなり飼いならされています。2 番目のものはもう少しあいまいですが、言語の表現力を利用してコード サイズと余分な変数を削減します。

Java や C# が好きな人は最初の方法 (object.member) を選び、Ruby や Python が好きな人は後者を選ぶと思います。

于 2010-06-26T03:21:15.660 に答える
6

Delphi の経験があるので、 withを使用するのは最終手段のサイズ最適化であり、安全性を検証するために静的コード分析にアクセスできるある種の JavaScript ミニマイザー アルゴリズムによって実行される可能性があります。

withステートメントを自由に使用することで発生する可能性のあるスコープの問題は、a** の王室の苦痛になる可能性があり、コードで he.. が起こっていることを理解するためにデバッグ セッションを経験することは望ましくありません。 、意図したグローバル変数または外部スコープ変数ではなく、オブジェクトメンバーまたは間違ったローカル変数をキャプチャしたことがわかります。

スコープを明確にするためにドットが必要な点で、VB のwithステートメントの方が優れていますが、Delphi のwithステートメントは、ヘアトリガーを備えた装填済みの銃であり、JavaScript のステートメントは同じ警告を正当化するのに十分類似しているように見えます。

于 2008-09-14T19:24:29.270 に答える
5

with の使用は推奨されておらず、ECMAScript 5 厳密モードでは禁止されています。推奨される代替方法は、一時変数にアクセスするプロパティを持つオブジェクトを割り当てることです。

出典: Mozilla.org

于 2012-10-24T15:15:52.480 に答える
4

withステートメントを使用して、コードサイズを小さくしたり、プライベートクラスメンバーに使用したりできます。例:

// demo class framework
var Class= function(name, o) {
   var c=function(){};
   if( o.hasOwnProperty("constructor") ) {
       c= o.constructor;
   }
   delete o["constructor"];
   delete o["prototype"];
   c.prototype= {};
   for( var k in o ) c.prototype[k]= o[k];
   c.scope= Class.scope;
   c.scope.Class= c;
   c.Name= name;
   return c;
}
Class.newScope= function() {
    Class.scope= {};
    Class.scope.Scope= Class.scope;
    return Class.scope;
}

// create a new class
with( Class.newScope() ) {
   window.Foo= Class("Foo",{
      test: function() {
          alert( Class.Name );
      }
   });
}
(new Foo()).test();

withステートメントは、スコープを変更する場合に非常に役立ちます。これは、実行時に操作できる独自のグローバルスコープを持つために必要なものです。定数を設定したり、「toUpper」、「toLower」、「isNumber」、「clipNumber」などのようによく使用される特定のヘルパー関数を設定したりできます。

よく読むパフォーマンスの悪さについて:関数のスコープはパフォーマンスに影響を与えません。実際、私のFFでは、スコープ付き関数はスコープなしよりも高速に実行されます。

var o={x: 5},r, fnRAW= function(a,b){ return a*b; }, fnScoped, s, e, i;
with( o ) {
    fnScoped= function(a,b){ return a*b; };
}

s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
    r+= fnRAW(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );

s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
    r+= fnScoped(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );

したがって、上記の方法でwithステートメントを使用しても、パフォーマンスに悪影響はありませんが、コードサイズが小さくなり、モバイルデバイスのメモリ使用量に影響を与えるため、優れた効果があります。

于 2010-02-05T13:08:37.857 に答える
3

比較的複雑な環境で実行されるコードをコンテナーに入れるのに適しています。私はこれを使用して、「ウィンドウ」のローカル バインディングを作成し、Web ブラウザー用のコードを実行します。

于 2010-04-04T04:19:04.843 に答える
3

オブジェクト リテラルの使用は興味深いと思います。たとえば、クロージャーを使用するためのドロップインの代替品です。

for(var i = nodes.length; i--;)
{
       // info is namespaced in a closure the click handler can access!
       (function(info)
       {           
            nodes[i].onclick = function(){ showStuff(info) };
       })(data[i]);
}

または、クロージャーに相当する with ステートメント

for(var i = nodes.length; i--;)
{
       // info is namespaced in a closure the click handler can access!
       with({info: data[i]})
       {           
            nodes[i].onclick = function(){ showStuff(info) };
       }        
}

本当のリスクは、with ステートメントの一部ではない変数を誤って無視することだと思います。そのため、オブジェクト リテラルが with に渡されるのが好きです。コードに追加されたコンテキストでそれがどうなるかを正確に確認できます。

于 2010-04-08T17:50:18.730 に答える
3

with を使用すると、多くの実装でコードが遅くなります。これは、すべてがルックアップ用の追加のスコープにラップされるためです。JavaScript で with を使用する正当な理由はありません。

于 2008-09-14T20:05:11.780 に答える
3

いくつかの短いコードでは、放射モードではなく度モードsinでなどの三角関数を使用したいと思います。cosこの目的のために、私はAngularDegreeオブジェクトを使用します:

AngularDegree = new function() {
this.CONV = Math.PI / 180;
this.sin = function(x) { return Math.sin( x * this.CONV ) };
this.cos = function(x) { return Math.cos( x * this.CONV ) };
this.tan = function(x) { return Math.tan( x * this.CONV ) };
this.asin = function(x) { return Math.asin( x ) / this.CONV };
this.acos = function(x) { return Math.acos( x ) / this.CONV };
this.atan = function(x) { return Math.atan( x ) / this.CONV };
this.atan2 = function(x,y) { return Math.atan2(x,y) / this.CONV };
};

with次に、ブロック内で言語ノイズを増やすことなく、度数モードで三角関数を使用できます。

function getAzimut(pol,pos) {
  ...
  var d = pos.lon - pol.lon;
  with(AngularDegree) {
    var z = atan2( sin(d), cos(pol.lat)*tan(pos.lat) - sin(pol.lat)*cos(d) );
    return z;
    }
  }

つまり、オブジェクトを関数のコレクションとして使用し、制限されたコード領域で直接アクセスできるようにします。これは便利だと思います。

于 2012-04-09T17:47:45.780 に答える
3

テンプレート言語を JavaScript に変換する場合、with 文が役立つと思います。たとえばJST in base2ですが、私はそれをより頻繁に見てきました。

withステートメントなしでこれをプログラムできることに同意します。しかし、それは何の問題も与えないので、それは合法的な使用です.

于 2008-09-15T10:27:25.997 に答える
3

with私は、次のステートメントでこのあいまいさの一部を排除する「マージ」関数を作成しました。

if (typeof Object.merge !== 'function') {
    Object.merge = function (o1, o2) { // Function to merge all of the properties from one object into another
        for(var i in o2) { o1[i] = o2[i]; }
        return o1;
    };
}

と同様に使用できますがwith、影響を与えるつもりのないスコープには影響しないことがわかります。

使用法:

var eDiv = document.createElement("div");
var eHeader = Object.merge(eDiv.cloneNode(false), {className: "header", onclick: function(){ alert("Click!"); }});
function NewObj() {
    Object.merge(this, {size: 4096, initDate: new Date()});
}
于 2010-08-12T19:24:19.257 に答える
2

object.member と入力するよりも with を使用する方が読みやすいとは思えません。読みにくいとは思いませんが、読みやすくもないと思います。

lassevk が言ったように、非常に明示的な「object.member」構文を使用するよりも、 with を使用するとエラーが発生しやすくなることが確実にわかります。

于 2008-09-14T19:43:43.810 に答える
2

の有用性はwith、コードがどれだけうまく書かれているかに依存すると思います。たとえば、次のようなコードを書いているとします。

var sHeader = object.data.header.toString();
var sContent = object.data.content.toString();
var sFooter = object.data.footer.toString();

with次に、これを行うことでコードの可読性が向上すると主張できます。

var sHeader = null, sContent = null, sFooter = null;
with(object.data) {
    sHeader = header.toString();
    sContent = content.toString();
    sFooter = content.toString();
}

逆に、デメテルの法則に違反していると主張することもできますが、そうではないかもしれません。余談=)。

何よりも、Douglas Crockford がを使用しないことwithを推奨していることを知っておいてください。ここで、彼のブログ投稿withとその代替案を確認することをお勧めします。

于 2008-10-06T22:08:50.517 に答える
1

W3schools http://www.w3schools.com/js/js_form_validation.aspの JavaScript でフォームの検証を確認する必要があります。ここでは、オブジェクト フォームが「スキャン」されて「email」という名前の入力が検索されます。

しかし、フォーム内のフィールドの名前や数量に関係なく、すべてのフィールドが空ではないことを検証する任意のフォームから取得するように変更しました。さて、私はテキストフィールドのみをテストしました。

しかし with() は物事をより簡単にしました。コードは次のとおりです。

function validate_required(field)
{
with (field)
  {
  if (value==null||value=="")
    {
    alert('All fields are mandtory');return false;
    }
  else
    {
    return true;
    }
  }
}

function validate_form(thisform)
{
with (thisform)
  {
    for(fiie in elements){
        if (validate_required(elements[fiie])==false){
            elements[fiie].focus();
            elements[fiie].style.border='1px solid red';
            return false;
        } else {elements[fiie].style.border='1px solid #7F9DB9';}
    }

  }
  return false;
}
于 2010-09-08T09:20:24.093 に答える
1

CoffeeScript のCocoフォークにはwithキーワードがありますが、ブロック内のターゲット オブジェクトに設定するだけです (CoffeeScript/Coco のthisように書き込み可能)。@これによりあいまいさが解消され、ES5 の厳格なモードへの準拠が達成されます。

with long.object.reference
  @a = 'foo'
  bar = @b
于 2011-06-15T16:13:31.060 に答える
0

withオブジェクトに格納されている値に基づいて、オブジェクトリテラルに新しい要素を追加するための良い使用法は次のとおりです。これが私が今日使用した例です:

使用できるタイルのセット(開口部が上、下、左、または右を向いている)があり、ゲームの開始時に常に配置およびロックされるタイルのリストをすばやく追加する方法が必要でした。 。types.tbrリスト内のタイプごとに入力し続けたくなかったので、を使用しwithました。

Tile.types = (function(t,l,b,r) {
  function j(a) { return a.join(' '); }
  // all possible types
  var types = { 
    br:  j(  [b,r]),
    lbr: j([l,b,r]),
    lb:  j([l,b]  ),  
    tbr: j([t,b,r]),
    tbl: j([t,b,l]),
    tlr: j([t,l,r]),
    tr:  j([t,r]  ),  
    tl:  j([t,l]  ),  
    locked: []
  };  
  // store starting (base/locked) tiles in types.locked
  with( types ) { locked = [ 
    br,  lbr, lbr, lb, 
    tbr, tbr, lbr, tbl,
    tbr, tlr, tbl, tbl,
    tr,  tlr, tlr, tl
  ] } 
  return types;
})("top","left","bottom","right");
于 2013-01-20T19:06:35.103 に答える
0

Andy E が Shog9 の回答のコメントで指摘したようにwith、オブジェクト リテラルを使用すると、予期しない動作が発生する可能性があります。

for (var i = 0; i < 3; i++) {
  function toString() {
    return 'a';
  }
  with ({num: i}) {
    setTimeout(function() { console.log(num); }, 10);
    console.log(toString()); // prints "[object Object]"
  }
}

予期しない動作がの特徴ではなかっwithわけではありません。

それでもこの手法を使用したい場合は、少なくとも null プロトタイプを持つオブジェクトを使用してください。

function scope(o) {
  var ret = Object.create(null);
  if (typeof o !== 'object') return ret;
  Object.keys(o).forEach(function (key) {
    ret[key] = o[key];
  });
  return ret;
}

for (var i = 0; i < 3; i++) {
  function toString() {
    return 'a';
  }
  with (scope({num: i})) {
    setTimeout(function() { console.log(num); }, 10);
    console.log(toString()); // prints "a"
  }
}

ただし、これは ES5+ でのみ機能します。も使用しないでくださいwith

于 2014-04-25T06:26:42.500 に答える
0

withrequire.js を使用するときにアリティを明示的に管理する必要を回避するために使用できます。

var modules = requirejs.declare([{
    'App' : 'app/app'
}]);

require(modules.paths(), function() { with (modules.resolve(arguments)) {
    App.run();
}});

requirejs.declare の実装:

requirejs.declare = function(dependencyPairs) {
    var pair;
    var dependencyKeys = [];
    var dependencyValues = [];

    for (var i=0, n=dependencyPairs.length; i<n; i++) {
        pair = dependencyPairs[i];
        for (var key in dependencyPairs[i]) {
            dependencyKeys.push(key);
            dependencyValues.push(pair[key]);
            break;
        }
    };

    return {
        paths : function() {
            return dependencyValues;
        },
    
        resolve : function(args) {
            var modules = {};
            for (var i=0, n=args.length; i<n; i++) {
                modules[dependencyKeys[i]] = args[i];
            }
            return modules;
        }
    }   
}
于 2013-09-25T18:38:34.123 に答える
0

アプリケーションの一部の動作を変更するために、ユーザーがコードをアップロードできるようにするプロジェクトに取り組んでいます。このシナリオでは、私はwith句を使用して、彼らのコードが私が混乱させたい範囲外のものを変更しないようにしています。これを行うために使用するコードの(簡略化された)部分は次のとおりです。

// this code is only executed once
var localScope = {
    build: undefined,

    // this is where all of the values I want to hide go; the list is rather long
    window: undefined,
    console: undefined,
    ...
};
with(localScope) {
    build = function(userCode) {
        eval('var builtFunction = function(options) {' + userCode + '}');
        return builtFunction;
    }
}
var build = localScope.build;
delete localScope.build;

// this is how I use the build method
var userCode = 'return "Hello, World!";';
var userFunction = build(userCode);

このコードは、ユーザー定義コードがwindow、クロージャーを介してローカル変数などのグローバルスコープのオブジェクトにもアクセスできないことを (ある程度) 保証します。

賢明な言葉として、ユーザーが送信したコードに対して静的コード チェックを実行し、他の卑劣な方法でグローバル スコープにアクセスしていないことを確認する必要があります。たとえば、次のユーザー定義コードは、 への直接アクセスを取得しますwindow

test = function() {
     return this.window
};
return test();
于 2014-11-03T04:22:28.903 に答える
-1

独自の巧妙な方法で、きれいな構文とあいまいさのない「with()」機能を取得できることを追加したかっただけです...

     //utility function
  function _with(context){
           var ctx=context;
           this.set=function(obj){
             for(x in obj){
                //should add hasOwnProperty(x) here
                ctx[x]=obj[x];
             }
       } 

       return this.set;          
 }

 //how calling it would look in code...

  _with(Hemisphere.Continent.Nation.Language.Dialect.Alphabet)({

      a:"letter a",
      b:"letter b",
      c:"letter c",
      d:"letter a",
      e:"letter b",
      f:"letter c",
     // continue through whole alphabet...

  });//look how readable I am!!!!

..または、あいまいさやカスタムメソッドなしで「with()」を本当に使用したい場合は、匿名関数でラップして.callを使用します

//imagine a deeply nested object 
//Hemisphere.Continent.Nation.Language.Dialect.Alphabet
(function(){
     with(Hemisphere.Continent.Nation.Language.Dialect.Alphabet){ 
         this.a="letter a";
         this.b="letter b";
         this.c="letter c";
         this.d="letter a";
         this.e="letter b";
         this.f="letter c";
         // continue through whole alphabet...
     }
}).call(Hemisphere.Continent.Nation.Language.Dialect.Alphabet)

ただし、他の人が指摘しているように、できるので少し無意味です...

 //imagine a deeply nested object Hemisphere.Continent.Nation.Language.Dialect.Alphabet
     var ltr=Hemisphere.Continent.Nation.Language.Dialect.Alphabet 
     ltr.a="letter a";
     ltr.b="letter b";
     ltr.c="letter c";
     ltr.d="letter a";
     ltr.e="letter b";
     ltr.f="letter c";
     // continue through whole alphabet...
于 2015-04-17T04:28:44.030 に答える