2

I'm having some trouble with thh following code:

var num_passengers;


function vehicleConstructor(name, num_wheels, num_passengers)
{
    var vehicle = {};
    vehicle.name = name;
    vehicle.num_wheels = num_wheels;
    vehicle.num_passengers = num_passengers;

    vehicle.makenoise = function() {

    }
    return vehicle;
}

var bus = vehicleConstructor("bus", 5, 10);

bus.pickUpPassengers = function(toPickUp){
    num_passengers += toPickUp;
    return num_passengers;
} 


 bus.pickUpPassengers(5);

I’ve added a global num_passengers for the pickUpPassengers() to avoid it being undefined.

However, I’m still receiving a NAN for the pickUpPassegers method of the bus instance.

Is it a matter of scoping or definition?

Maurius
  • 33
  • 2
  • this should help http://stackoverflow.com/a/13522017 – Dhiraj Jun 08 '16 at 16:33
  • `num_passengers` is never initialized with a value. What you are referencing inside `pickUpPassengers` is the global variable you defined at the top, not the vehicle instance property you added to the object in `vehicleConstructor`. – AtheistP3ace Jun 08 '16 at 16:34
  • `num_passengers` is undefined. – Sebastian Simon Jun 08 '16 at 16:34
  • 1
    inside `bus.pickUpPassengers()` `this.num_passengers` is the value bound to the `bus` instance if thats what your looking for ... (i.e would return 15) – Alex K. Jun 08 '16 at 16:35

3 Answers3

1

It is a matter of num_passengers definition. You should init it as a number at the beginning:

var num_passengers = 0;

But if you want to change value of num_passengers of your bus Object, you should use this and throw out first definition of num_passengers:

bus.pickUpPassengers = function(toPickUp){
    this.num_passengers += toPickUp;
    return this.num_passengers;
}
Anton Temchenko
  • 1,440
  • 1
  • 13
  • 28
  • 2
    This would be true if the intention is for all instances of a vehicle to share a single cumulative value, I don't think thats the case. – Alex K. Jun 08 '16 at 16:42
1

Just one small problem on finding the current instance. You simply need to define which instance you need for num_passengers with 'this'.

Also, This way you do not need the global variable for num_passengers, which means you can have multiple instances( car, bus, and motorcycle) at the same time. This will potentially avoid future problems.

function vehicleConstructor(name, num_wheels, num_passengers)
{
    var vehicle = {};
    vehicle.name = name;
    vehicle.num_wheels = num_wheels;
    vehicle.num_passengers = num_passengers;

    vehicle.makenoise = function() {

    }
    return vehicle;
}

var bus = vehicleConstructor("car", 5, 10);

bus.pickUpPassengers = function(toPickUp){
    this.num_passengers += toPickUp;
    return this.num_passengers;
} 
Ian T
  • 46
  • 5
1

Here is how I would write your code:

function Vehicle (name, options) {
  this.name = name
  this.wheels = options.wheels
  this.passengers = options.passengers
}

Vehicle.prototype.makeNoise = function () {
  console.log('vroom')
  return this
}

var bus = new Vehicle('bus', { wheels: 4, passengers: 10 })

bus.pickUpPassengers = function (toPickUp) {
  this.passengers += toPickUp
  return this
}

bus.pickUpPassengers(5)

This uses JavaScript's prototypical inheritance, which can be used like classes in other languages. Constructors start with a capital letter (by convention) and are called with new. Using prototypes also means that you don't define methods like makeNoise every time you create a new vehicle, instead all the vehicles refer back to the prototype.

I've also used return this at the end of the methods as it allows chaining:

// Without chaining:
foo.bar()
foo.baz()
foo.qux()

// With chaining:
foo.bar().baz().qux()

The Vehicle constructor also takes the numbers of wheels and passengers in an options object, which makes it easier to read and understand what the numbers are for.


With ES6 it would look like this:

class Vehicle {
  constructor (name, { wheels, passengers } = {}) {
    this.name = name
    this.wheels = options.wheels
    this.passengers = options.passengers
  }
  makeNoise () {
    console.log('vroom')
    return this
  }
}

class Bus extends Vehicle {
  constructor (options) {
    super('bus', options)
  }
  pickUpPassengers (toPickUp) {
    this.passengers += toPickUp
    return this
  }
}

const bus = new Bus({ wheels: 4, passengers: 10 })
bus.pickUpPassengers(10)

(Here I chose to make Bus a subclass of Vehicle because it's easier with ES6. It also helps you if you want to create more than one bus.)

gcampbell
  • 1,252
  • 15
  • 13