简体   繁体   中英

How to choose what argument a variable is assigned to in a function? -Javascript

Given a normal function as such;

function descriptions(awesome, cool, alright){
   return (awesome || "no one") + " is awesome. " + cool + " is cool. " +
     + alright + " is alright";
}
descriptions("jane", "jack", "jefferson");
//returns "jane is awesome. jack is cool. jefferson is alright."

I would like to use the same function, but would only like to pass it the final two arguments like so:

descriptions(cool : "john", alright : "jane"); //I would like a statement similar to this that works.
//should return "no one is awesome. jack is cool. jefferson is alright."

How would the above be done?

Something different syntactically but similar semantically might be achieved using object destructuring

function descriptions({ awesome = 'no one', cool, alright }) {
    return awesome + " is awesome. " + cool + " is cool. " +
     + alright + " is alright";
}

Then you just invoke it with an object with corresponding properties:

descriptions({ cool: 'a', alright: 'b'});

That is not possible in any variety of ECMAScript (including JavaScript).

It is theoretically possible to do things like use conditional, custom logic:

function(a,b,c){
   if(arguments.length === 1) {
      // we're in object mode;
      b = a.b
      c = a.c
      a = a.a || 'default';
   }
}

But that is not a built in part of the language.

This is NOT possible, for example:

function foo(a,b,c){return a/(b || 1) + c;}
foo({c:1,b:2,a:3})

There is also the possibility to conditionally define values based on number of arguments:

function say (a,b,c) {
   if(arguments.length === 2) {
      c = b;
      b = a;
      a = 'cat';
   }
   console.log('a ' + a + ' likes a ' + b + ' and a ' + c)
}
say('dog', 'bone', 'walk') // a dog likes a bone and a walk
say('mouse', 'bowl of milk') // a cat likes a mouse and a bowl of milk

Yes you can certainly achieve this! You can use a clever trick many developers use to set a variable to a default value if one is not provided.

function descriptions(awesome, cool, alright){
awesome = awesome || "";
if (awesome === "")
{
    return "no one" + " is awesome. " + cool + " is cool. " +
 + alright + " is alright";
}
else{
    return awesome + " is awesome. " + cool + " is cool. " +
 + alright + " is alright";
}

}
console.log(descriptions(undefined, "jack", "jefferson"));

Here is the working code. You could also pass an empty string.

In ECMAScript 6, this can sort of be done if you change your parameters to receive an object and take advantage of destructuring assignment .

 function descriptions({awesome: awesome = "no one", cool: cool = "", alright: alright = ""} = {}) { return awesome + " is awesome. " + cool + " is cool. " + alright + " is alright"; } var res = descriptions({ cool: "john", alright: "jane" }); document.body.textContent = res; 

So we have someone of an emulation of named parameters. Only thing extra needed by the caller is the curly braces.

Of course browser support is limited, but transpilers are available.

You can do this by passing an object:

function descriptions(info) {
    // Avoid TypeError if no argument is passed
    if (!info) {
        info = {};
    }

    return (info.awesome || "no one") + " is awesome. " + (info.cool || "no one") + " is cool. " + (info.alright || "no one") + " is alright.";
}

// Use:
console.log(descriptions({
    awesome: "Strong Bad",
    cool: "The Cheat",
    alright: "Strong Sad"
}));

You could use a different approach:

var coolLevels = {
  isCool: ["Jack", "John"]
, isAlright: ["Jane", "Jefferson"]
, isAwesome: []
}

function describe(people, coolLevel, phrase) {
  return people.filter(function(person){
    return Boolean(coolLevel.indexOf(person))
  }).join(", ") + phrase
}

function descriptions(people){
  var awesome = describe(people, coolLevels.isAwesome, ' is awesome.')
  var cool = describe(people, coolLevels.isCool, ' is cool.')
  var alright = describe(people, coolLevels.isCool, ' is alright.')

  return awesome + cool + alright
}

demo: https://jsbin.com/kahawuhelu/edit?js,console,output

You can pass undefined , null or "" as the first parameter. Eg:

descriptions(null, "jack", "jefferson");

Since you already use awesome || "no one" awesome || "no one" , any falsy value will be good enough.


Another approach would be changing the function to receive an object:

function descriptions(options) {
  return (options.awesome || "no one") + " is awesome. " + options.cool + " is cool. " + 
    options.alright + " is alright";
}

descriptions({ cool: "jack", alright: "jefferson" });

Now, depending on your browser support, you can use ES6 destructuring parameters:

const descriptions = ({ awesome = 'no one', cool, alright }) => (
  `${awesome} is awesome. ${cool} is cool. ${alright} is alright`
);

descriptions({ cool: 'jack', alright: 'jefferson' });

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