Exposing a method which is inside a closure

前端 未结 4 492
栀梦
栀梦 2021-02-07 11:21

When we are creating a method inside a closure it becomes private to that closure and can\'t be accessed until we expose it in some way.

How can it be exposed?

相关标签:
4条回答
  • 2021-02-07 11:53

    You expose functions or properties of a closure by internally declaring them in this scope (which can change depending on invocation).

    function example(val) {
    
        var value = val;
    
        this.getVal = function() {
            return value;
        }
    
        this.setVal = function(v) {
            value = v;
        }
    }
    
    var ex = new example(2);
    ex.getVal();  // == 2
    ex.setVal(4); // == null
    ex.getVal();  // == 4
    

    Methods declared in this can access variables declared using var, but not the other way 'round.

    function example(val) {
    
        var value = val;
    
        var double = function(v) {
            return 2 * v;
        }
    
        this.getDouble = function() {
            return double(value);
        }
    }
    
    
    var ex = new example(2);
    ex.getDouble(); // == 4
    

    The function closes over the scope. What you want to do is to return a reference to a function that has access to the scope you require so you can invoke it at a later point.

    If you need to create a function that calls a specific method at some later point,

    var ex = new example(2);
    var delayed_call = function() {
        return(ex.getDouble()); // == 4, when called
    }
    setTimeout(delayed_call, 1000);
    

    If scoping is an issue,

    var ex = new example(2);
    var delayed_call = (function(ex_ref) {
        return function() {
            return(ex_ref.getDouble()); // == 4, when called
        }
    })(ex); // create a new scope and capture a reference to ex as ex_ref
    setTimeout(delayed_call, 1000);
    

    You can inline most of this with the less readable example of,

    setTimeout((function(ex_ref) {
        return function() {
            return(ex_ref.getDouble()); // == 4, when called
        })(new example(2))) 
        , 1000
    );
    

    setTimeout is just a convenient way of demonstrating execution in new scope.

    var ex = new example(2);
    var delayed_call = function() {
        return(ex.getDouble());
    }
    delayed_call(); // == 4
    
    0 讨论(0)
  • 2021-02-07 11:54

    You need to pass it to the outside in some manner.

    Example: http://jsfiddle.net/patrick_dw/T9vnn/1/

    function someFunc() {
    
        var privateFunc = function() {
            alert('expose me!');
        }
    
        // Method 1: Directly assign it to an outer scope
        window.exposed = privateFunc;
    
        // Method 2: pass it out as a function argument
        someOuterFunction( privateFunc );
    
        // Method 3: return it
        return privateFunc;
    }
    
    someFunc()(); // alerts "expose me!"
    
    function someOuterFunction( fn ) {
        fn(); // alerts "expose me!"
    }
    
    window.exposed(); // alerts "expose me!"
    
    0 讨论(0)
  • 2021-02-07 11:56

    You can return a reference to it...

    var a = function() {
    
       var b = function() {
          // I'm private!
          alert('go away!');
       };
    
       return {
          b: b // Not anymore!
       };
    
    };
    

    See it on jsFiddle.

    You could also bind it to the window object. But I prefer the method above, otherwise you are exposing it via a global variable (being a property of the window object).

    0 讨论(0)
  • 2021-02-07 12:09

    For performance purposes you can invoke it this way:

    var a = (function(){
       function _a(){}
       _a.prototype = (function(){
         var _test = function(){ console.log("test"); };
         return {
           test: _test
         }
       }());
    
      return new _a();
    }());
    
    // usage
    var x = a;
    x.test(); // "test"
    
    0 讨论(0)
提交回复
热议问题