2

I want to use array.filter(my_func()) when processing 5 different arrays of user inputs to elegantly return the array without the element the user just deleted, with a private filterInput class variable. However, my_func() when used as an inner call doesn't have "this" context.

Is there a better way to do this? Would rather not write the same filter function in 5 different callers just to keep scope.

MyClass
    private inputArray1: string[];
...
    private filterInput: string;
...
    private filterFunc(element, index, array) {
        return (element !== this.filterInput);
    }
...
    public caller1(input: string) {//this is called from the onclick() in the HTML
        this.filterInput = input;
        this.inputArray1 = this.inputArray1.filter(this.filterFunc());
    }

Anyone know how to accomplish this without scrapping the filter utility and just writing my own using search then return slice1 + slice2?

4
  • 2
    Look into lambdas ("arrow functions") Commented Mar 3, 2019 at 6:25
  • 1
    Do you really need to store the .filterInput on your instance at all? Commented Mar 3, 2019 at 15:07
  • @Bergi, not necessarily if there's a better way to do it (which the parameterised double return solution below looks to be). It's just the first thing that came to mind. I am an Angular novice on a big project with a tight timeline just doing what feels natural in other languages I've used. Primary backgrounds are Java and C++. I'm always open to learning though. Commented Mar 3, 2019 at 21:51
  • @patrickjp93 Thanks, I adjusted my answer below. The fourth snippet in malbarmawi's answer (if that's what you mean by "double return") is close, but you wouldn't even make a separate method to create the closure. Commented Mar 3, 2019 at 22:06

3 Answers 3

2

You can use functions bind method to fix this reference

public caller1(input: string) {
  this.filterInput = input;
  this.inputArray1 = this.inputArray1.filter(this.filterFunc.bind(this));
}

or you can use javascript arrow function

public caller1(input: string) {
  this.filterInput = input;
  this.inputArray1 = this.inputArray1.filter((elm,idx,arr) => this.filterFunc(elm,idx,arr));
}

another way be javascript functions closure 🧙‍♂️

private filterFunc() {
    const filterInput = this.filterInput;
    return function (element, index, array) {
         return (element !== filterInput);
}

public caller1(input: string) {
    this.inputArray1 = this.inputArray1.filter(this.filterFunc());
}

but I do prefer to use parameter like this to set the filter value

private filterFunc(filterInput) {
    return function (element, index, array) {
         return (element !== filterInput);
}

public caller1(input: string) {
    this.inputArray1 = this.inputArray1.filter(this.filterFunc(this.filterInput));
}

Closures 🚀🚀

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for that last answer. I love recyclable code.
0

Another possible way is to write your "filterFunc" like this (ts compiler will not put it on a prototype):

private filterFunc = (element, index, array) => {
    return (element !== this.filterInput);
}

And use it like this:

this.inputArray1 = this.inputArray1.filter(this.filterFunc);

Comments

0

For general solutions of how to solve this, see How to access the correct `this` inside a callback?, but for the filter method specifically just pass the context as the second argument:

this.inputArray1 = this.inputArray1.filter(this.filterFunc, this);
//                                                          ^^^^

This is relatively unidiomatic though. You wouldn't make the filterFunc an instance method at all, you'd just define a local function inside the caller1 method and make it a closure over the input parameter:

public caller1(input: string) {
    function filterFunc(element, index, array) {
        return (element !== input);
//                          ^^^^^
    }
    this.inputArray1 = this.inputArray1.filter(filterFunc);
//                                             ^^^^^^^^^^
}

or doing the same, but more concisely by defining the function inline as an expression, using arrow syntax and omitting the unneeded parameters:

public caller1(input: string) {
    this.inputArray1 = this.inputArray1.filter(element => element !== input);
}

1 Comment

I'm going with the closure answer to return the result of an inner function since it's more reusability. Thanks though.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.