views:

88

answers:

5

Hi,

I have the following code:

var HD = function() { };

HD.Car = (function() {
    var _date = "09/07/2010";
    return {
        Make: undefined,
        Model: undefined,
        showMakeAndModel: function() {
            document.write(this.Make + " " + 
                           this.Model + 
                           " (data correct as of " + _date + ")");
            }
        };
    })();

var bert = new HD.Car();
bert.Make = "Ford";
bert.Model = "Capri";
window.onload = bert.showMakeAndModel();

And get the following error:

HD.Car is not a constructor

All I'm trying to do is test (to learn) the 'singleton pattern' with closure (for private members) so not a 'real' example, but the book I'm reading suggests this is the way to do it.

So a little confused - any help would be much appreciated.. Rob

A: 

Remove new, because it is only needed for constructor functions. Now HD.Car will be the object that an anonymous and self-executing function returns. Then remove parens after HD.Car. So it should look like:

var bert = HD.Car;

Now HD.Car is a singleton.

If you want it to be more like a factory you should do:

HD.Car = function() {
    var _date = "09/07/2010";
    return {
        Make: undefined,
        Model: undefined,
        showMakeAndModel: function() {
            document.write(this.Make + " " + 
                           this.Model + 
                           " (data correct as of " + _date + ")");
        }
   };
};​

var bert = new HD.Car();
galambalazs
HD.Car is not a regular function... it's an object.
Luca Matteis
**every function is an object**. A regular function means that it is not a constructor function. Read before comment.
galambalazs
no, a function is not an object. If you're referring to the ability of doing `HD.something`, this is possible because `HD` is simply a namespace, not because it's a function. In fact `var HD = 3; HD.something = 4` will work also simply because JavaScript offers the ability to add attributes to namespaces, even if they're not objects.
Luca Matteis
:) ok 2 things here. I've misread the code above I should correct. But your last statement is still false. Functions are objects in js...
galambalazs
@galambalazs, again no, take a look at the `typeof` operator.
Luca Matteis
you mean the typeof operator which returns `object` even for `null`. The typeof operator doesn't really tell much about the language. **Functions are first-class objects in Javascript**. Learn to live with it.
galambalazs
What's wrong with `null` being an object? I'm not sure I can trust your un-referenceable answers.
Luca Matteis
You want lmgtfy??? **"Every function in JavaScript is actually a Function object." (mdc)** - source: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Function
galambalazs
`I'm not sure I can trust your un-referenceable answers.` ahahahaa xD
CIRK
Functions in JavaScript are not of type Object. They are however implemented as objects. Implementation is different than Definition. Just how in `var a = 3;` a is not an Object, it's a Number. However the Number type is implemented as an Object. This has NOTHING to do with the question at hand so stop introducing extra overhead to the argument.
Luca Matteis
*"However the Number type is implemented as an Object."* `var f = function(){}; f.prop = 5` vs `var a = 3; a.prop = 5`.
galambalazs
But as a last "un-reference" you could read wikipedia: JavaScript. *"Functions are first-class; they are objects themselves"*
galambalazs
If functions are treated as type 'object' then why can't you use the keyword `new` on all objects? again, we're not talking of how things are implemented in Javascript, rather how they work, and why it's important to understand the `type` of things (the `typeof` operator is not useless as you think).
Luca Matteis
I didn't say it's useless (nonsense sometimes? yes). But i'ts hilarious how you treat `typeof` as a language specification`. But why the heck you keep saying implementation? Hello! We're talking about a language here. :)
galambalazs
You should treat `typeof` as a language specification, stop confusing people.
Luca Matteis
Let's see the **language specification** says: `(4.3.11) Null Value: The null value is a primitive value that represents the null, empty, or non-existent reference.`, and **`Null Type: The type Null has exactly one value, called null.`** And yet **`typeof null`** will give you **object**. This indicates that **you've never read the specification**, and you're misinformed probably by one of the awful books out there.
galambalazs
I gave you **three** references and you called my statements "un-referenceable". Now, you show me some references of your misconceptions... But other than the actual specification they can only be the misconceptions of other people...
galambalazs
A: 

In JavaScript you can only use the new keyword with functions.

HD.Car is not a function, it's an object.

Just don't use new for your example.

Luca Matteis
How can I instansiate a new HD.Car object without the 'new' keyword?
LiverpoolsNumber9
@LiverpoolsNumber9 you can use new, and instansiate see my answer.
galambalazs
I did - thank you.
LiverpoolsNumber9
+3  A: 

You have some incorrect ()() around the HD.Car class definition. This fixed sample works:

var HD = function() { }; 

HD.Car = function() { 
    var _date = "09/07/2010"; 
    return { 
        Make: undefined, 
        Model: undefined, 
        showMakeAndModel: function() { 
            document.write(this.Make + " " +  
                           this.Model +  
                           " (data correct as of " + _date + ")"); 
            } 
        }; 
    }; 

var bert = new HD.Car(); 
bert.Make = "Ford"; 
bert.Model = "Capri"; 
window.onload = bert.showMakeAndModel();
David
Constructors shouldn't return anything.
Luca Matteis
I agree, however, I believe he is using the pattern where return is used to ensure if it is accidently called as a function, it has the same result.
David
Yes, but the attributes `Make` and `Model` you assign will not refer to the attributes of the `HD.Car` instance, rather they are just attributes of the `bert` namespace.
Luca Matteis
Luca I think you might be on to something here as the intellisense (VS) is not picking up "bert.showMakeAndModel()" - however, firstly this does work, and secondly, "_date" works as a private member. I do need a solution where "bert.showMakeAndModel()" appears in intellisense though...
LiverpoolsNumber9
@LiverpoolsNumber9, I don't feel like helping you anymore, please read a book.
Luca Matteis
By the way - David - thanks for this. Forgot to say!
LiverpoolsNumber9
*"Yes, but the **attributes** Make and Model you assign will not refer to the attributes of the HD.Car instance, rather they are just attributes of the bert **namespace**. "* and *"I don't feel like helping you anymore, please read a book"* - that's hilarious...
galambalazs
@ Luca Matteis 1.) they are properties not attributes. 2.) there are no namespaces in the language 3.) a constructor function returns an object reference, just as the example above. *"Constructors shouldn't return anything"* - constructors return *this* by default. But you can return another object, then the default will be garbage collected. This is how you emulate private variables in js. 4.) read a book yourself
galambalazs
A: 

Your error is coming from the fact that you're executing your constructor function, as indicated by the open and close parentheses after the declaration of HD.Car (and just before var bert). So, the function is executing and returning an object, which you're then trying to use with the "new" operator.

If you remove those parentheses, I believe you'll get the functionality you want.

Ryan Kinal
+1  A: 

For a bit more info:

How to write a singleton class in javascript.

Hopefully that will shed a bit more light for you!

Terry Donaghe
Thanks Terry :)
LiverpoolsNumber9