Object literal as prototype - javascript

This question is more about support and backwards compatibility. I have tested the following code.
function newFunc() {}
newFunc.prototype = {
literal : {
init : function() {
console.log(this);
this.test();
},
test : function() {
console.log('test');
}
}
}
var inst = new newFunc();
inst.literal.init();
This works, though I've not seen object literals as prototypes in any other code. Is there a reason for this? This seems like a logical way of coding to me though I don't want to pursue it if it has serious pitfalls.

It's perfectly normal to use an object literal to create the prototype for a function, but normally only as the actual value of the prototype object.
What's unusual is doing what you've done and include a nested object within the prototype.
In effect you've only added one object to the prototype, the one named literal. All of the methods are then properties of that object. It's technically valid syntax, but I've never seen it used before. As #squint points out in the comments, it also appears to break the way that the this variable works, because it binds this to the "next left" property that was used in the function call:
var inst = new newFunc();
inst.literal.init();
> Object { init: function, test: function }
i.e. this has been set to point at the .literal object, and not at the actual instance that has been created.

Yes, using literals for prototype is correct. For example Mozilla explicitly uses a literal in the prototype's documentation:
var Customer = function(name) {
this.name = name;
}
var Person = { // this is a literal
canTalk : true,
greet : function() { /* ... */ }
}
Customer.prototype = Person;
Some explanation: Value of prototype is an object. It doesn't matter how the object was created - using simply {} is fine. It is often initialized using something like MyClass1.prototype = new MyClass2(), but new just creates a new object. It also sets the prototype property and executes the constructor (MyClass2) but on the new object, it doesn't affect MyClass1 in any way (see explanation here).
Using a nested literal doesn't make a difference. In the question, the prototype is set to { literal : { ... } }. What actually happens when you call inst.literal.init() is:
The runtime looks at inst and checks whether the object has a value assigned for property literal.
inst dos not have such property, therefore the runtime continues with its prototype property
inst.prototype references the literal object to which it was initialized. This object has assigned a value for property literal.
inst.literal therefore evaluates to the nested literal inst.prototype.literal
The literal object does have a value for property init
The init() function is called
This is one of the principles of JavaScript (ECMA Script) so there should be no compatibility issues.

What you are doing is setting the prototype to be a JavaScript object with several properties. This is perfectly acceptable, as functions act very similarly to objects in JavaScript. All JavaScript does is passes the reference to this prototype property down to inherited objects, so they will not have a function they can access, but an object instead in this case.
You can see that this is actually done in the MDN documentation:
var Person = {
canTalk : true,
greet : function() {
if (this.canTalk) {
console.log("Hi, I'm "+this.name)
}
}
}
Customer.prototype = Person;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fprototype

if i understand it right they say you can do that in javascript (ECMA SCRIPT)
http://en.wikipedia.org/wiki/Literal_(computer_programming)
but what i know is that if you want to instance your Object there is an issue for old browsers..that you cannot instance objects with the Object.create() function
so you should generally do like this...
var foo = function(){};
foo.prototype = {func:function(){}}
var bar = new foo();
like you do so or so :)

Related

how can i use object literal pattern in place of constructor function

I am trying to learn different object declaration type and inheritance. Here, first I declared an object named parent using an object constructor. Then, another object child is introduced which inherits all the properties from parent.
Parent object using constructor is:
function parent(){
this.parent_last_name="khan";
this.occupation="business";
}
Then a child object is declared and I make it inherit all the properties and methods from parent object using
child.prototype=new parent();
In the same example, I replaced the constructor type declaration and used object literal type declaration.
var parent={
name: "khan",
occupation: "business",
ask: function(){
alert("what do you do?");
},
};
It is giving me an error that "parent is not a constructor".and it is not printing anything.
My question is :
1) Why is the object literal is not working with this particular example? When do I use object literal type and when do I use a constructor?
2)advantage of constructor over object literal
and 3)literal type object declaration can do what i want to do here?
WHOLE CODE
<html>
<body>
<script>
function parent() {
this.parent_last_name = "khan";
this.occupation = "business";
}
parent.prototype.ask = function() {
alert("what do you do?");
}
function child() {
this.child_name = "mohsin";
this.occupation = "student";
}
child.prototype = new parent();
var lol = new child();
document.write(lol.child_name + " " + lol.parent_last_name);
</script>
</body>
</html>
Browser: Firefox
An object literal is just an instance of Object while a constructor function is an instance of Function which can become a constructor when new operator is used behind it (i.e. new SomeFunc()).
Remember that functions are JavaScript's first-citizen constructs. They can be either old-school procedural functions, object methods and also object constructors.
When to use object constructors? Easy: when you want to reuse the same object structure across same or other script files and you might need prototype chain (inheritance).
If you need an object to be passed as argument of some function call or something like that, object literals is the way to go.
Anyway, whenever you create a function (either constructor function or not), you've a prototype available to define members that will be part of any instance created with the whole function. Since ECMA-Script 5.x you can also use Object.create(...):
var A = function() {};
A.prototype.doX = function();
Object.create(A.prototype, {
doY: {
value: function() { }
}
});
Object.create approach is also another way to get inheritance in JavaScript, since it creates an object where its prototype is the one provided as first parameter of the whole function.
About the error...
You can't use an object literal using new operator and this is why Web browsers (or ECMA-Script runtimes...) will throw an error, because an object literal is an instance of Object rather than being of Function.

Purpose of this Javascript prototype snippet

Sorry I can't phrase this better. But I ran across some code like the following:
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
And I just can't seem to figure out what it does. MyObject is defined above it something like this:
function MyObject(options) {
this.someProp = someDefault;
this.otherProp = process(options.something);
// etc...
}
and it's always called as a constructor. I'm just wondering what benefit those first two lines provide and if it's a known pattern in Javascript.
I just can't seem to figure out what it does
It creates a new object that inherits from [the old] MyObject.prototype via Object.create and then overwrites MyObject.prototype with that. It also explicitly adds a .constructor property which actually should be existing already.
I'm just wondering what benefit those first two lines provide
None, unless before that snippet someone has corrupted the prototype (like MyObject.prototype = Object.prototype) and this is an attempt to fix it.
…and if it's a known pattern in Javascript.
Not like this. Using Object.create to set up the prototype chain for inheritance between constructor-defined "classes" is a known pattern, but then the constructors would be different on each side of the assignment.
The two lines of code provided seem to be an incorrect attempt of the use of prototypal inheritance, but I see where you're going with this and what you're trying to accomplish.
As we know, there are two ways in JavaScript to define objects that have properties and methods as members - the object literal notation and function notation. Using object literal notation, we don't have immediate access to the new keyword (think of this like using abstract classes in Java or C#). With function notation, we have access to the new keyword because the initial declaration of an object as a function serves as our constructor.
In ECMAScript 5, The Object object was given a method called create that provided developers a simple way to create a new object from an existing object declared with the object literal notation. (See documentation here). However, objects created in function notation have problems with this method because they are Function objects. The Object.create method is a great way to use simple inheritance, allowing access to the base properties and methods.
With function notation, once the new keyword is used, the result is not a function, but rather an object. For example, I can test this:
var Obj = function(){};
console.log(typeof Obj) // "function"
console.log(typeof new Object()); // "object"
Because of this, you can only inherit once (meaning the child object cannot be derived from):
var MyObject = new Object();
var anotherObj = new MyObject() // throws exception
To alleviate this problem, you need to follow three steps:
Create your child object in function notation (so you can create new instances of it using the new keyword and inherit from it).
Set the child object's prototype (an object) to the result of a new instance of the base object (which will be an object as well).
Set the constructor of the child object (which happens to be on the object's prototype) back to reference the Function of itself (which is a function prior to instantiation). If you don't do this, the constructor will remain an object, which cannot spawn new instances.
From here, you can create new instances of both the child and parent objects and derive from both, using the pattern. Here's a practical example:
var Vehicle = function(){};
Vehicle.prototype.start = function() {
return this.make + " " + this.model + " " + "started";
}
var Car = function(color, make, model) {
this.color = color;
this.make = make;
this.model = model;
}
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;
var myCar = new Car("red", "chevy", "aveo");
myCar.start(); //"chevy aveo started"
I really don't see any benefit in doing that.
What it's doing is providing the new object with the previous objects methods. But it's coming from the same object...
Here is a good example of JS inheritance:
http://jsfiddle.net/aDCmA/2/
var App = (function(){
var Being = function() {
this.living = true;
this.breathes = function () {
return true;
};
};
var Robert = function() {
this.blogs = true;
this.getsBored = function () {
return "You betcha";
}
};
Robert.prototype = new Being();
return {
Being: Being,
Robert: Robert,
being: function(){ return new Being(); },
robert: function(){ return new Robert(); }
}
}());
Here is another question that is similar: inherit prototype methods from other classes without overriding own prototype methods
Credit to Robert Nyman for originally blogging about it: http://robertnyman.com/2008/10/06/javascript-inheritance-how-and-why/
Let's see line by line:
MyObject.prototype = Object.create(MyObject.prototype);
This redefines MyObject.prototype to an object that inherits from MyObject.prototype. This is unusual, because it makes no sense to inherit from itself.
MyObject.prototype.constructor = MyObject;
Since the previous line overwrote MyObject.prototype, this is just fixing the constructor property that was lost in the process.
I can think of one scenario where tht might be useful: if some code before that messed up with MyObject.prototype, for example assigning the prototype of another constructor to it:
MyObject.prototype = SomethingElse.prototype; // wrong way to do inheritance.
Then the code you posted would be an attempt to fix it.
This is perfectly valid Javascript.
Any javascript function (say Func)can be used as a constructor and the constructor invocation also requires a prototype property (i.e. F.prototype or the prototype associated with the function) . Thus (almost) every function has a prototype property. The value of this property (i.e. Func.prototype).
Now the value of this prototype associated with the function is an object itself that has a single non enumerable property called constructor. And the value of this constructor property is the function object (i.e. F itself).
Lets take an example.
Say I construct a function Func
var Func = function() {
//your definition
};
Now since this can be invoked as a constructor it has to have a prototype property Func.prototype lets call this proto.
proto = Func.prototype;
Now the prototype has a single property (that is non enumerable) called constructor. This constructor has a value that is equal to the function object itself.
Dont believe me check it like this
Func.prototype.constructor === Func // =>true
Will always return true for any function.
Now from the code you explained :
So basically these two lines
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
are modifying the value of the prototye to have a constructor property with the value of MyObject that is defined. But that would have happened anyways in the normal course of things. But the reason could be that maybe the prototype of the object has been changed earlier from the class it has been inherited from. In that case would those two lines make sense.
Hope that helps :)

If there is no distinction between classes and objects why doesn't this code work?

I was always taught that in Javascript there is no distinction between objects and classes. Then can someone explain why this code generate error:
var firstObj = function() {};
firstObj.prototype.sayHi = function() {
document.write("Hi!");
};
firstObj.sayHi();
Whereas this one works:
var firstObj = function() {};
firstObj.prototype.sayHi = function() {
document.write("Hi!");
};
new firstObj().sayHi();
What's the difference? Why isn't the first one working?
The key issue here is that your firstObj variable is a Function object, not a firstObj object. This is a subtle distinction, but the type of object determines which prototype it inherits.
The prototype is like a template that is applied to newly created objects of a particular type. You must create a firstObj object (usually with new which invokes the constructor and assigns a prototype) in order to have that template applied to it. In the first example, your firstObj variable is a Function object, not a firstObj object so it has the prototype of a Function not of anything else..
In your second example, you actually create a firstObj object so it inherits the prototype for that type of object.
If you want the method applied in your first example so it works on the function object you've already created, just put the method directly on your already existing function object, not on the prototype.
There is no difference in the language between objects and classes1. However, there is a big difference between one kind of object and another. In the first case:
firstObj.sayHi();
you are trying to access the sayHi property of firstObj, which is a Function object that does not have such a property. (You could, however, do firstObj.prototype.sayHi().)
In the second case:
new firstObj().sayHi();
you are first invoking the new operator on the firstObj object, which evaluates to a new object. That new object has firstObj as it's constructor property and a prototype equal to the prototype property of firstObj. You are then accessing the sayHi property of that returned object, which succeeds because sayHi is in the prototype chain for that object.
1 Technically, JavaScript doesn't have classes2 (in the traditional sense), just constructor functions that are usually called "classes".
2 However, class is a future reserved word.
when you write this:
var firstObj = function() {};
you only define a constructor function, thus you need to use the key word new for the new objects created with this constructor function.
A function is just a function until new is issued. At that point, a Function Object is created based on the prototype for the function. That is why you will not see the sayHi method present in the first version.
Also, firstObj is a function, and not an object, so you need to invoke it to actually have anything happen. firstObj will not actually invoke the function, you must use firstObj().
Further, there are ways to have the prototype used without explicitly requiring the new keyword. This is done in a number of popular frameworks (such as jQuery). It is done by checking to see if new was used, and if it was not, then it news one up for you on the spot:
jsFiddle Demo
var firstObj = function() {
if( !(this instanceof firstObj) ){
return new firstObj();
}
};
firstObj.prototype.sayHi = function() {
alert("hi");
};
firstObj().sayHi();

How do I inherit a function from a base object and overwrite it in javascript

What I am trying to do is have a child object provide its own implementation for a function defined in a base object. As far as I've understood so far prototypes are the best (only!) way to go about doing this.
Note also that I am currently developing using the game engine: Turbulenz and as such I am trying to follow / stick to their style as closely as possible. In the engine "classes"/objects are defined and created in the following manner
function baseObject() { }
baseObject.prototype =
{
myMember1: 1,
myMember2: 2,
myMethod: function myMethodFn() {
return this.myMember1 + this.myMember2;
}
}
baseObject.Create = function baseObjectCreateFn
{
var o = new baseObject();
return o;
}
This would allow me to do the following
var anObject = baseObject.Create();
var someValue = anObject.myMethod(); // should return 3
What I would like to be able to do now is to create a new object that inherits all the properties of baseObject while allowing me to overwrite its myMethod function to for example subtract the two member values instead of add.
Would I be correct in saying that I will have to create another object then alter its prototype? The part thats throwing me most is that the definition of the baseObject's prototype is defined as an object literal and so I'm unsure of the syntax to overwrite one of its members, i.e. would the following be valid or not? :
function childObject() {}
childObject.prototype = baseObject.Create() // would this inherit from baseObject?
// or should it be: childObject.prototype = new baseObject();
// this is the part thats confusing me as the syntax
// doesn't quite match the original base objects prototype
// syntax and I'm unsure if that will matter
childObject.prototype.myMethod = function myMethodFn() {
return this.myMember1 - this.myMember2;
}
childObject.Create = function childObjectCreateFn
{
var o = new childObject();
return o;
}
var aChildObject = childObject.Create()
var anotherValue = aChildObject.myMethod() // would this return -1 as expected?
To summarise I'm trying to create an object that will overwrite a function that exists in a base object by inheriting the function from the base object and changing it, how do I do this? Thanks for your time.
You have it correct.
As for the syntax confusion, there is no real difference between
thing.prototype.myMethod = function () { ... }
and
thing.prototype = { myMethod: function() { ... } };
except for the fact that in the second one you are setting the prototype all at once (to an object literal), and if you do it again, you'll overwrite the prototype all at once with a new object literal. But because it is an object literal, you can't do inheritance this way (everything declared with naked braces { ... } is just an instance of Object of no special type). If you stick with the first syntax you'll always be ok.
Note that when you put:
childObject.prototype.myMethod = function myMethodFn() { ... }
The part where you put myMethodFn is actually ignored. The function is named myMethod by the fact that this is where you assigned it.
Similarly, where you have
childObject.Create = function childObjectCreateFn
you don't need childObjectCreateFn (it's ignored), and you need to put parentheses () somewhere after function or it's a syntax error.
Moving on to the reason why this works, every created object in Javascript has a prototype. When you call a method on that object, it first looks inside the object itself to see if a key corresponding to the name of the method exists. If not, it looks in the prototype object for the same thing, and if it's not there, it goes to that object's prototype, and so on, until it gets to the root Object, which has no prototype.
In this way you can override an implementation merely by naming it the same thing, but having it appear earlier in the prototype chain. That's exactly what you're doing on childObject. It retains the functionality of baseObject because you created an instance of baseObject to serve as childObject's prototype. Then you augmented childObject's prototype with a new method of the same name, but one that comes earlier in the prototype chain.

Difference between a constructor and an Object

I definitely need some light on this.
What's the diference between:
var MY_APP = function(){
this.firstMethod = function(){
//something
};
this.secondMethod = function(){
//something
};
};
and
var MY_APP = {
firstKey: function(){
//something
},
secondKey: function(){
//something
}
};
besides the obvious fact that one is a Function and the other an Object, what are the differences in code flow, prototypes, patterns... whatever, and when should we use the first or the second?
I'm so spaced out in this area that i'm not sure if i'm correctly explaining the doubt, but further info can be given if you ask.
The key difference between the two is in how they are intended to be used. A constructor, as its name suggests, is designed to create and set up multiple instances of an object. An object literal on the other hand is one-off, like string and number literals, and used more often as configuration objects or global singletons (e.g. for namespacing).
There are a few subtleties about the first example to note:
When the code is executed, an anonymous function is created and assigned to MY_APP, but nothing else happens. firstMethod and secondMethod don't exist until MY_APP is explicitly called.
Depending on how MY_APP is called, the methods firstMethod and secondMethod will end up in different places:
MY_APP(): Since no context is supplied, the this defaults to window and the methods will become global.
var app1 = new MY_APP(): Due to the new keyword, a new object is created and becomes the default context. this refers to the new object, and the methods will get assigned to the new object, which subsequently gets assigned to app1. However, MY_APP.firstMethod remains undefined.
MY_APP.call(YOUR_APP): This calls my MY_APP but sets the context to be another object, YOUR_APP. The methods will get assigned to YOUR_APP, overriding any properties of YOUR_APP with the same names. This is a really flexible method that allows multiple inheritance or mixins in Javascript.
Constructors also allow another level of flexibility since functions provide closures, while object literals do not. If for example firstMethod and secondMethod rely on a common variable password that is private to the object (cannot be accessed outside the constructor), this can be achieved very simply by doing:
var MY_APP = function(){
var password = "GFHSFG";
this.firstMethod = function(){
// Do something with password
alert(password); // Woops!
};
this.secondMethod = function(){
// Do something else with password
};
};
MY_APP();
alert(password); // undefined
alert(MY_APP.password); // undefined
The first is a function, the second is an object literal. Since Functions in JS are first class objects, a function can have properties on it, just like any other object can.
Typically, if you want to create a "class" that you might be familiar with from classical inheritance languages, you would do something like
function MyClass() {...}
as is documented here http://www.crockford.com/javascript/inheritance.html
To answer the question posed in your edits, you would use them both in different situations. Object literals are used to pass configurations around. A typical usage pattern would be a method that accepts an object literal like so
something.init({
length: 10,
height: 10,
text: 'some text'
});
and so on.
You could use something similar to your first example when creating a namespace. Javascript has some interesting language features in that you can have so-called "self-invoking functions" that are of the form:
var myApp = (function(){
var firstMethod = function() {...}
...
})();
the motivations behind doing something like this are detailed here
http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/
You can also investigate the differences via your favorite javascript debugging console. In firebug and chrome, I did the following:
var ol = {}; ol.prototype;
var fn = function(){}; fn.prototype;
the first line prints undefined, the second returns a prototype with a constructor of 'function'
The constructor can be reused as is, the object literal would need to be repeated or wrapped in a function to be reused.
Example of wrapping the object literal in a function:
function MY_APP() {
return {
firstKey: function(){
//something
},
secondKey: function(){
//something
}
};
}
The object created using the constructor will have it's constructor property set to the constructor function. However, as you used an anonymous function assigned to a variable instead of a named function, the constructor will still be nameless.
Other than that, there isn't really any differences. Both create anonymous functions that are assigned to the properties of the object, so the resulting objects are the same. You can compare this to assigning named functions to the properties, or using prototype functions, both having the difference that each function only exists once instead of being created over and over for each object.
There is some confusion in JavaScript regarding the difference between a function and an object.
In the first case,
var MY_APP = function() { this.v = 7; ... }
or
function MY_APP(x) { this.v = x; ... }
a function is declared, not an object. In MY_APP, this refers to the global object.
Meaning that calling the function MY_APP(7) will assign v globally to the value of 7. (and in your case the function firstMethod would be declared globally).
MY_APP(3); // The global variable v is set to 3
MY_APP(4); // The global variable v is overwritten and set to 4
To use MY_APP as an object, it needs to be instantiated, for instance
var obj1 = new MY_APP(3);
var obj2 = new MY_APP(4);
will have obj1.v to be 3, and obj2.v to be 4.
Note you can also add methods using the prototype keyword (instead of this.firstMethod...)
MY_APP.prototype.firstMethod = function () { ... }
In the second case
var MY_APP = { ... };
an object, one object, is created and its name is MY_APP. The this keywords refers to that object, MY_APP.

Categories

Resources