web-dev-qa-db-ja.com

JavaScriptがスコープを別の関数に渡す

関数のスコープをどうにかして別の関数に渡すことは可能ですか?

例えば、

function a(){
   var x = 5;
   var obj = {..};
   b(<my-scope>);
}

function b(){
   //access x or obj....
}

私はむしろ変数に直接アクセスする、つまりthis.athis.objのようなものを使用せず、xまたはobjを直接使用するだけです。

34
ciochPep

関数aのプライベートスコープに本当にアクセスする唯一の方法は、b内でaを宣言して、aへの暗黙的なアクセスを可能にするクロージャーを形成することです。変数。

ここにいくつかのオプションがあります。

直接アクセス

  1. b内でaを宣言します。

    function a() {
       var x = 5,
          obj = {};
       function b(){
          // access x or obj...
       }
       b();
    }
    
    a();
    
  2. bの内部にaが必要ない場合は、両方をより大きなコンテナースコープ内に含めることができます。

    function container() {
       var x, obj;
       function a(){
          x = 5;
          obj = {..};
          b();
       }
       function b(){
          // access x or obj...
       }
    }
    
    container.a();
    

これらは、aの変数をbで直接使用して、移動するための追加のコードなしで使用できる唯一の方法です。 「ヘルプ」や間接参照に少し満足している場合は、さらにいくつかのアイデアを紹介します。

間接アクセス

  1. 変数をパラメーターとして渡すことができますが、オブジェクトのプロパティ以外には書き込みアクセス権はありません。

    function a() {
       var x = 5,
          obj = {};
       b(x, obj);
    }
    
    function b(x, obj){
       // access x or obj...
       // changing x here won't change x in a, but you can modify properties of obj
    }
    
    a();
    

    これのバリエーションとして、次のように更新された値をaに渡すことにより、書き込みアクセスを取得できます。

    // in a:
    var ret = b(x, obj);
    x = ret.x;
    obj = ret.obj;
    
    // in b:
    return {x : x, obj : obj};
    
  2. bオブジェクトに、aのプライベート変数にアクセスできるゲッターとセッターを渡すことができます。

    function a(){
       var x = 5,
          obj = {..},
          translator = {
             getX : function() {return x;},
             setX : function(value) {x = value;},
             getObj : function() {return obj;},
             setObj : function(value) {obj = value;}
          };
       b(translator);
    }
    
    function b(t){
       var x = t.getX(),
          obj = t.getObj();
    
       // use x or obj...
       t.setX(x);
       t.setObj(obj);
    
       // or you can just directly modify obj's properties:
       obj.key = value;
    }
    
    a();
    

    ゲッターとセッターはパブリックであり、thisaオブジェクトに割り当てられますが、この方法では、aから明示的に与えられた場合にのみアクセスできます。

  3. また、変数をオブジェクトに入れて、オブジェクトを渡すこともできます。

    function a(){
       var v = {
          x : 5,
          obj : {}
       };
       b(v);
    }
    
    function b(v){
       // access v.x or v.obj...
       // or set new local x and obj variables to these and use them.
    }
    
    a();
    

    バリエーションとして、代わりに呼び出し時にオブジェクトを作成できます。

    function a(){
       var x = 5,
          obj = {};
       b({x : x, obj: obj});
    }
    
    function b(v){
       // access v.x or v.obj...
       // or set new local x and obj variables to these and use them.
    }
    
    a();
    
27
ErikE

スコープは関数によって作成され、スコープは関数に留まるため、あなたが求めていることに最も近いのは、a()からb()に関数を渡すことです。関数は、a()からスコープ変数に引き続きアクセスできます。

_function a(){
   var x = 5;
   var obj = {..};
   b(function() { /* this can access var x and var obj */ });
}
function b( fn ){

    fn(); // the function passed still has access to the variables from a()

}
_

b()は、関数が渡した変数に直接アクセスすることはできませんが、参照が渡されたデータ型(オブジェクトなど)は、関数が渡された場合にアクセスできますreturnsそのオブジェクト。

_function a(){
   var x = 5;
   var obj = {..};
   b(function() { x++; return obj; });
}
function b( fn ){

    var obj = fn();
    obj.some_prop = 'some value'; // This new property will be updated in the
                                  //    same obj referenced in a()

}
_
8
user113716

bindの使用について

function funcA(param) {     
    var bscoped = funcB.bind(this);     
    bscoped(param1,param2...)
}
6
vittore

番号。

ローカルスコープオブジェクトにアクセスしています。 [[Context]]

あなたはできません公的にアクセスできます。

Node.jsなので、[[Context]]オブジェクトへのアクセスを提供するC++プラグインを作成できるはずです。 I highly JavaScript言語に独自の拡張機能をもたらすため、これはお勧めしません。

6
Raynos

他の人が言ったように、そのようなスコープを渡すことはできません。ただし、自己実行型の無名関数を使用して(または、知識があればすぐに実行して)、変数のスコープを適切に設定できます。

(function(){
    var x = 5;
    var obj = {x:x};
    module.a = function(){
        module.b();
    };
    module.b = function(){
        alert(obj.x);    
    };
}());

a();
2
david

あなたは「スコープを通過する」ことはできません...私が知っていることではありません。
applyまたはcallを使用して関数が参照しているオブジェクトを渡し、現在のオブジェクト(this)を最初のパラメーターとして代わりに送信できます関数を呼び出すだけです:

function b(){
    alert(this.x);
}
function a(){
    this.x = 2;
    b.call(this);
}

関数が特定のスコープにアクセスする唯一の方法は、そのスコープで宣言することです。
ややこしい。
それは次のようなものにつながります:

function a(){
    var x = 1;
    function b(){
        alert(x);
    }
}

しかし、それは一種の目的を無効にするでしょう。

2
gion_13

canで行う最も簡単なことは、あるスコープからそのスコープ外の関数へのpass変数であると思います。参照渡し(オブジェクトなど)の場合、b has 'access' to it(以下のobj.somepropを参照):

function a(){
   var x = 5;
   var obj = {someprop : 1};
   b(x, obj);
   alert(x); => 5
   alert(obj.someprop); //=> 'otherval'
}
function b(aa,obj){
   x += 1; //won't affect x in function a, because x is passed by value
   obj.someprop = 'otherval'; //change obj in function a, is passed by reference
}
2
KooiInc