简体   繁体   中英

Angular 6+ How to use inner functions with class variables?

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?

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 🚀🚀

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM