Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to invoke outer "this" in inner function?

I defined two functions for array:

Array.prototype.remove = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            this.removeAt(i);
        }
    }
};
Array.prototype.removeAll = function(array2) {
    array2.forEach(function(item) {
        this.remove(item);  // remove not found!!
    });
}

But in the removeAll function, it reports function remove is not found. I fix it like this:

Array.prototype.removeAll = function(array2) {
    var outer = this;
    array2.forEach(function(item) {
        outer.remove(item);  
    });
}

But it's ugly. Is there a better way?

like image 721
Freewind Avatar asked Dec 23 '11 09:12

Freewind


People also ask

Can an inner function access outer variable?

Python Inner Functions or Nested Functions can access the variables of the outer function as well as the global variables. The inner functions variable has a local scope that is limited only to that function.

Can inner function call outer function?

With a nested function, the inner function operates within the scope of the outer function, including having access to the outer function's variables and arguments. The outer function, though, does not have access to the inner function's variables, nor does the calling application have access to the inner function.

How do you access outer this in Javascript?

You can bind the "outer" instance to the "inner" function by invoking the bind method on the inner function. Learn more at MDN. Or use an arrow function. I see you answered in 2016 so that should be an option.

In which scope A variable declared in outer function can also accessed by the inner function is called?

Nested functions have access to variables declared in their outer scope. In this particular example, the scope is called a function scope, because the variable is accessible and only accessible within the function body where it's declared.


2 Answers

Passing this via a different variable as you do is the idiomatic approach. There is nothing ugly about it. (It is more common to call the variable that or self though)

like image 181
Quentin Avatar answered Oct 10 '22 09:10

Quentin


An alternative to using bind (if you need to support old browsers and don't wish to extend Function.prototype) is to simply wrap your callback in an immidate function and feed this in as an argument like this:

Array.prototype.removeAll = function(array2) {
    array2.forEach(function(outer){
     return function(item) {
        outer.remove(item);  
    };}(this));
}

or you can write a simple curry utility function and use like this

function curry() {
  var fn = Array.prototype.shift.call(arguments), 
      args = Array.prototype.slice.call(arguments);
  return function curryed() {
    return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));
  };
};



Array.prototype.removeAll = function(array2) {
    array2.forEach(curry(function(item) {
        outer.remove(item);  
    },this));
}

If you don't mind extending Function.prototype you can use bind as already described by others you can find an excellent compatibility extension on MDN here: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

like image 25
Martin Jespersen Avatar answered Oct 10 '22 09:10

Martin Jespersen