You don't assign _instance to the object, it's just a closure variable, and should be accessed without using this:
var Dog = function() {
var _instance = 'hello world';
return function() {
console.log(_instance);
}
} (); //note that it is self invoking function
var l = new Dog();
I'd probably write it like so instead:
var Dog = (function() {
var defaults = {
name: 'Rags'
};
var Dog = function (options) {
// Take options as a constructor argument, this
// allows you to merge it with defaults to override
// options on specific instances
this.setOptions(options);
};
Dog.prototype = {
// Common methods for Dogs here
setOptions: function (options) {
// Declare all variables in the beginning of the method because
// JavaScript hoists variable declarations
var key = null;
// First assign all the defaults to this object
for ( key in defaults) {
this[key] = defaults[key];
}
// Now override with the values in options:
if (options && options.hasOwnProperty) {
for ( key in options ) {
this[key] = options[key];
}
}
}
};
return Dog; // Return the constructor method
} ()); // wrap the self-invoked function in paranthesis to visualize that
// it creates a closure
var buster = new Dog({name: 'Buster'}),
unnamed = new Dog();
alert(buster.name); // Alerts 'Buster'
alert(unnamed.name); // Alerts 'Rags'
Note that I have not tried to compile the above code, so it might contain a few mistakes. Nothing JsLint can't handle though!
You might want to consider adding filtering to the setOptions method so that it doesn't assign properties you don't want, or filter out methods etc declared in the options-parameter.
Additionally, if you use JQuery, or similar library, there are (often) utility functions for merging objects, making it trivial to write the setOptions-method:
function setOptions (options) {
// I assume JQuery here
// true as the first argument gives us a recursive merge
var mergedOptions = $.extend(true, defaults, options);
for (var key in mergedOptions ) {
if(this.checkAllowedProperty(key, typeof(mergedOptions[key])) {
this[key] = mergedOptions[key];
}
}
}
/**
* This method checks if propertyName is an allowed property on this object.
* If dataType is supplied it also checks if propertyName is allowed for
* dataType
* @return true if propertyName, with type dataType, is allowed on this object,
* else false
*/
function checkAllowedProperty (propertyName, dataType);