2

I'm setting up an object constructor and would like to pass an key/value object as a parameter. I was wondering what would be the correct way to do so? Right now I'm just passing the keys as the parameters:

(function() {
    function Venue(name, poor, satisfactory, excellent) {
        this.name = name;
        this.serviceRatings = {
            poor: poor,
            satisfactory: satisfactory,
            excellent: excellent
        };
    }

  var dining = new Venue("dining", .1, .15, .2);

  console.log(dining["serviceRatings"]["satisfactory"] // .15
}());

Although this works, coming from a Ruby background it only felt right to pass the object itself and assign the it's values in the initializer. This was the best equivalent I could think of:

class Venue
  def initialize(name, serviceRatings = {})
    @name = name
    @poor = serviceRatings[:poor]
    @satisfactory = serviceRatings[:satisfactory]
    @excellent = serviceRatings[:excellent]
  end
end

Is there a way to do this in Javascript? The way I have things written now makes me feel as if I'm bloating my constructer's list of parameters (unless this is the right way to do this).

1
  • Can pass in one object argument instead of multiple primitives if that is what you are asking. Not really clear what you want to do Commented Mar 20, 2016 at 12:49

4 Answers 4

2

You can pass an object just like you did in your ruby class.

function Venue(name, options) {
    this.name = name;
    this.serviceRatings = options;
}

var dining = new Venue("dining",{
        poor: .1,
        satisfactory: .15,
        excellent: .2
    });

Above will create the same output as before. It's worth to mention that ecmascript 2015 brought classes to javascript - so you could also write it like this:

class Venue {
    constructor(name, options = {}) {
        this.name = name;
        this.serviceRatings = options;
    }
}

Above we're using an empty object as default parameter, which is also an es2015 feature.

If you want to have default key names, something like this will make it

class Venue {
    constructor(name, options = {}) {
        this.name = name;
        this.serviceRatings = Object.assign({
           poor: undefined,
           satisfactory: undefined,
           excellent: undefined
        }, options);
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

For either example, is there a way to write default key names within the options object? Just curious.
Yes, edited my answer @CarlEdwards - this will work in both examples - but be aware that Object.assign hasn't best browser support, so you might need to polyfill it depending on the environment you're running this in
Thanks. I'm hoping more browsers support the second method soon. Much more convenient.
Yes, I feel the same.. @CarlEdwards
2

Do you mean something like this?

(function() {
        function Venue(name, serviceRatings) {
            this.name = name;
            this.serviceRatings = serviceRatings;
        }

        var dining = new Venue("dining", {
            poor:.1,
            satisfactory:.15,
            excellent:.2
        });

        console.log(dining["serviceRatings"]["satisfactory"]) // .15
    }());

Comments

1

As others have pointed out, it is possible to pass an object as an argument.

// naive ES5 version
function Venue(name, serviceRatings) {
    this.name = name;
    this.serviceRatings = serviceRatings;
}

The problem with this naive approach is that Objects in JavaScript are mutable. If you assign the Object like above, your object state can be mutated accidentally. For example:

var ratings = { poor: 0, satisfactory: 2, excellent: 8 };
var diner = new Venue('diner', ratings);

ratings.poor = 12;
var burgerJoint = new Venue('my burgers', ratings);

Here you mutate ratings after diner was created, and you accidentally set diner.serviceRatings.poor to 12.

You can protect your code from this by copying the values of your object:

// improved with Object.assign
function Venue(name, serviceRatings) {
    this.name = name;
    this.serviceRatings = Object.assign({}, serviceRatings);
}

Object.assign() copies every property from seviceRatings to {}; this way later modifications to the other object do not affect your member property.

If you are using ES2015, you can use object destructuring, which has additional benefits: it makes your expected data structure explicit; and allows you to specify default values:

// ES2015 version with explicit parameters and default values
function Venue(name, { poor = 0, satisfactory = 0, excellent = 0 }) {
    this.name = name;
    this.serviceRatings = { poor, satisfactory, excellent };
}

Edit: as seen in another answer, if you are using ES2015, you might as well as use the class syntactic sugar:

// ES2015 version using class definition
class Venue
    constructor (name, { poor = 0, satisfactory = 0, excellent = 0 }) {
        this.name = name;
        this.serviceRatings = { poor, satisfactory, excellent };
    }    
}

Comments

0

arguments will contain all the parameters passed to the function as a list.

(function() {
    function Venue() {
        console.log(arguments);
    }

    var dining = new Venue("dining", .1, .15, .2);

}());

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.