-1

I'm trying to understand why this and prototype behave differently in the constructor vs. the new instance. In the following code Aircraft.range returns undefined. I can't understand why it doesn't return 2,000 like the new instance.

function Aircraft() {
    this.range = '2,000 Km';
}

let mustang = new Aircraft();

console.log('Aircraft.range ', Aircraft.range);
console.log('mustang.range ', mustang.range);

This attempt using prototype produces the same result.

function Aircraft() {}

Aircraft.prototype.range = '2,000 Km';

let mustang = new Aircraft();

console.log(Aircraft.range);
console.log(mustang.range);

**** Update ****

I've read many articles on prototypes and instances but theory only goes so far. This is a specific question used to work out the mechanics of these ideas. The answers I received helped me understand this concept better than a dozen articles talking about theory. I'm sure that these answers will help other people trying to learn the fundamentals of Javascript.

DR01D
  • 1,325
  • 15
  • 32
  • 1
    I really don't know why you would expect them to behave the same, instances and constructors are completely different things. – user229044 Mar 31 '18 at 00:27
  • No kidding. They're different? It's all clear now. – DR01D Mar 31 '18 at 00:29
  • 2
    Yes, they are different. If you said `x.size = function() { }` and then asked why `y.size` is undefined, that would be the same as the question you've asked. – user229044 Mar 31 '18 at 00:29
  • Possible duplicate of [How does JavaScript .prototype work?](https://stackoverflow.com/questions/572897/how-does-javascript-prototype-work) – Jared Smith Mar 31 '18 at 00:34
  • 1
    It only looks the same because you used a scalar. Consider: `function Foo(){ this.notShared = { a: 1 } }; Foo.prototype.shared = { b: 2 }; var foo = new Foo(); var bar = new Foo(); bar.shared.b = 3; console.log(foo.shared.b); // 3!!`. The `notShared` of each instance can be safely mutated, but if you have a mutable object on the prototype all the instances point to the same object. – Jared Smith Mar 31 '18 at 00:40
  • @JaredSmith that concept I understand. It's basically like opening two different windows to the same room. Alter something in the room and it doesn't matter which window you're looking through you see the same alteration. – DR01D Mar 31 '18 at 00:47

2 Answers2

3

Here's a simple explanation for all three cases:

  • this.range means that range is a property of the created instance only.
  • Aircraft.prototype.range means that range is a property of all instances you'll create because it's defined in the constructor's prototype.
  • Aircraft.range means that range is a property of the constructor (because functions are objects) and is not related to instances. Instances can only access that property by using this.constructor.range.
Angel Politis
  • 10,955
  • 14
  • 48
  • 66
  • Ok interesting I can follow that. But in no case is `range` a property of the constructor? – DR01D Mar 31 '18 at 00:31
  • and neither define `Aircraft.range` (oops, the edit explained that) - if you want `Aircraft.range` to be "something" you have to set `Aircraft.range` to "something" – Jaromanda X Mar 31 '18 at 00:31
  • @Angle Politis ok that makes sense! Thank you for explaining all three examples. I wouldn't have understood without being able to compare all 3. Thanks! – DR01D Mar 31 '18 at 00:38
1

Something that really helped me understand this was understanding exactly what the new keyword does.

new Aircraft means:

  1. create an object ("{}")
  2. call the Aircraft function with the object as this (setting .range on that object to "2,000 Km"
  3. set the prototype of that object to Aircraft.prototype

You could sort of implement it yourself like this:

function _new ( constructor ) {
    var instance = {};
    constructor.call( instance );
    instance.prototype = constructor.prototype;
    return instance;
}

_new( Aircraft ) is roughly equivalent to new Aircraft().

Ben West
  • 4,398
  • 1
  • 16
  • 16
  • It might sound simple but knowing that `new` means create `{ }` does help cement that in my brain. – DR01D Mar 31 '18 at 00:51