简体   繁体   中英

Where does the value in my function come from?

I am currently working my way through the functional JavaScript exercise at http://nodeschool.io .

I have the following exercise:

Return a function that takes a list of valid users, and returns a function that returns true if all of the supplied users exist in the original list of users.

You only need to check that the ids match.

Example:

var goodUsers = [
    { id: 1 },
    { id: 2 },
    { id: 3 }
];

// `checkUsersValid` is the function you'll define

var testAllValid = checkUsersValid(goodUsers);

testAllValid([
    { id: 2 },
    { id: 1 }
]);

// => true

testAllValid([
    { id: 2 },
    { id: 4 },
    { id: 1 }
]);

// => false

Arguments:

  • goodUsers : a list of valid users

Use array.some and array.every to check whether every user passed to your returned function exists in the array passed to the exported function.

The answer to the task is:

function checkUsersValid(goodUsers) {
    return function (submittedUsers) {
        return submittedUsers.every(function (submittedUser) {
            return goodUsers.some(function (goodUser) {
                return submittedUser.id === goodUser.id;
            });
        });
    };
}

module.exports = checkUsersValid;

However, I do not understand where the values for submittedUsers is coming from given that:

var testAllValid = checkUsersValid(goodUsers);

And that the function is called with:

testAllValid([
    { id: 2 },
    { id: 1 }
]);

// => true

Shouldn't that above equate to:

checkUsersValid([
    {id:2},
    {id:1}
]);

In this case where am i getting the values for submittedUsers ?

We know that:

function checkUsersValid(goodUsers) {
    return function (submittedUsers) {
        return submittedUsers.every(function (submittedUser) {
            return goodUsers.some(function (goodUser) {
                return submittedUser.id === goodUser.id;
            });
        });
    };
}

We also know that:

var goodUsers = [
    { id: 1 },
    { id: 2 },
    { id: 3 }
];

var testAllValid = checkUsersValid(goodUsers);

Hence by substitution:

var goodUsers = [
    { id: 1 },
    { id: 2 },
    { id: 3 }
];

var testAllValid = function (submittedUsers) {
    return submittedUsers.every(function (submittedUser) {
        return goodUsers.some(function (goodUser) {
            return submittedUser.id === goodUser.id;
        });
    });
};

Finally, we call:

testAllValid([
    { id: 2 },
    { id: 1 }
]);

What does it evaluate to?

var goodUsers = [
    { id: 1 },
    { id: 2 },
    { id: 3 }
];

var submittedUsers = [
    { id: 2 },
    { id: 1 }
];

// it evaluates to:

submittedUsers.every(function (submittedUser) {
    return goodUsers.some(function (goodUser) {
        return submittedUser.id === goodUser.id;
    });
});

If you evaluate it you'll see that every submittedUser is also a goodUser . Hence the answer is true .

First of all, checkUsersValid just creates a function and returns the created function. Invoking it with any input, will get you another function. So,

checkUsersValid([
    {id:2},
    {id:1}
]);

will be returning you another function. Now, if you think about what checkUsersValid does, it accepts a list of whitelisted users and returns a function which checks if the list of users to be validated is in the whitelisted users.

So, checkUsersValid creates a function to check the whitelisted users and testAllValid is the function which does the actual validation. They both are doing different tasks.

Now, you might be wondering why would we do it like this, instead of doing like

testAllValid(listOfValidUsers, listOfUsersToBeValidated);

If listOfValidUsers is a static list, and you are going to use testAllValid in multiple places (even in places where listOfValidUsers will not be in scope), then you need to figure out a way to make listOfValidUsers available for testAllValid . Instead, we create a new function with checkUsersValid , which can remember the listOfValidUsers (because of the closure property), you just need to make sure that the function object is available everywhere. That would make the code less cumbersome.

There are two level of closures here. In the first level you submit all the valid users (ie goodUsers ) and it returns a function (ie, testAllValid ).

The testAllValid function is also a closure which takes a parameter (ie, submittedUsers ) and returns the final result.

please read javascript closure for detail

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