JavaScript 将作用域传递给另一个函数

JavaScript pass scope to another function

本文关键字:另一个 函数 作用域 JavaScript      更新时间:2023-09-26

是否有可能以某种方式将一个函数的作用域传递给另一个函数?

例如

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

我宁愿直接访问变量,即不使用 this.athis.obj 之类的任何东西,而只是直接使用 xobj

真正访问函数a私有作用域的唯一方法是在a内部声明b,这样它就形成了一个闭包,允许隐式访问a的变量。

以下是为您提供的一些选项。

直接访问

  1. a内声明b

    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();
    

这些是你能够直接在b中使用a变量的唯一方法,而无需一些额外的代码来移动东西。如果你满足于一点点"帮助"和/或间接,这里有更多的想法。

间接访问

  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一个对象传递一个带有 getter 和 setter 的对象,这些对象可以访问 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();
    

    getter 和 setter 可以是公共的,分配给 athis对象,但这样它们只有在从 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();
    

作用域是由函数创建的,作用域与函数保持在一起,因此最接近您要求的内容是将函数从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()不能像函数那样直接访问传递的变量,但如果传递的函数返回该对象,则可以访问传递引用的数据类型(如 Object(。

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()
}

使用bind怎么样

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

No.

您正在访问本地范围对象。[[Context]] .

您无法公开访问它。

现在,由于它是节点.js您应该能够编写一个C++插件,使您可以访问[[Context]]对象。我强烈建议不要这样做,因为它为 JavaScript 语言带来了专有扩展。

你不能"通过范围"...不是我知道的。
您可以使用 applycall 传递函数引用的对象,并将当前对象 ( this ( 作为第一个参数发送,而不仅仅是调用函数:

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

函数访问特定作用域的唯一方法是在该作用域中声明。
有点棘手。
这将导致类似这样的东西:

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

但这会有点违背目的。

正如其他人所说,你不能像那样传递范围。但是,您可以使用自执行的匿名函数正确限定变量的范围(如果您迂腐,则可以立即执行(:

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

我认为您可以做的最简单的事情就是将变量从一个作用域传递到该作用域之外的函数。如果你通过引用传递(如对象(,b可以"访问"它(参见下面的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
}

你真的只能用 eval 来做到这一点。 下面将给出函数 b 函数 a 的作用域

  function a(){
     var x = 5;
     var obj = {x};
     eval('('+b.toString()+'())');
  }
  
  function b(){
     //access x or obj....
     console.log(x);
  }
  
  a();  //5
function a(){
   this.x = 5;
   this.obj = {..};
   var self = this;
   b(self);
}
function b(scope){
   //access x or obj....
}
function a(){
   var x = 5;
   var obj = {..};
   var b = function()
   {
        document.println(x);
   }
   b.call();
}

你有没有试过这样的事情:

function a(){
   var x = 5;
   var obj = {..};
   b(this);
}
function b(fnA){
   //access x or obj....
   fnA.obj = 6;
}

如果您可以将函数 B 作为方法函数 A 站立,请执行以下操作:

function a(){
   var x = 5;
   var obj = {..};
   b(this);
   this.b = function (){
      // "this" keyword is still === function a
   }
}