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

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.

Related

differences between prototype and namespace

In namespace we can use something like this:
var namespace = {};
namespace.something.nested.namespacing();
And also in prototype we can use same like name the namespace:
something.prototype.method();
In both types we are using . notation. So, how can we determine the code is using namespace or prototype?
JavaScript doesn't have namespaces. What you're calling a namespace is just an object. It's fairly common to use objects to stand in for namespaces.
Your code:
var namespace = {};
namespace.something.nested.namespacing();
...creates an object and a variable that refers to that object called namespace. Then you add properties to that object (it looks like you've added a property, something, which is also an object, which has a property, nested, which is also an object, which has a property called namespacing which refers to a function).
Your code:
something.prototype.method();
...is also using an object. The above would actually be a really unusual thing to do, you're calling a function (method) by directly referring to the prototype property of what I assume is a function (something). That's not normally what you would do. Normally you'd create an object via the function:
var s = new something();
...and then use the prototype that got assigned to s implicitly:
s.method();
The prototype property on functions can be confusing to people new to JavaScript. It's just a normal property like any other property, which is on function instances. The only thing that makes it special is the new operator: When you call a function via new:
var s = new something();
...the JavaScript engine creates a new, blank, object, then sets its underlying prototype (sometimes called __proto__ but that's not in the spec [yet]) using something.prototype, like this:
// pseudo-code for `var s = new something()`
var tmp = {}; // New, blank object
tmp.__proto__ = something.prototype; // Assign a prototype to the new object
something.call(tmp); // Call `something` with `this` referring to `tmp`
s = tmp; // Assign the result to `s`
(There's a detail I left out in the above to avoid confusing matters, to do with the special case where something has an explicit return statement in it that returns an object reference.)
Well, namespaces are just objects and prototype objects are objects, so from a syntactic point of view, there is no difference how you access them (foo.bar is called dot notation().
However, they serve two fundamentally different purposes:
Namespaces are used to structure your code and to avoid global namespace pollution.
Prototypes are used to share methods between multiple instances of the same constructor function.
So you usually don't call a method directly on the prototype because it most likely won't work. The purpose of this method is to be called on an instance of the corresponding constructor function. For example:
function Something() {}
Something.prototype.foo = function() {};
var s = new Something();
s.foo();
The . notation is a very general purpose tool used in javascript for accessing any properties of any object.
var x = {};
x.val = 2;
Your reference to a namespace is just a general purpose object in javascript as there is no actual namespace type in javascript. In other words, plain objects are used to create namespace-like things in javascript. So, as such, object properties are used to keep track of names in the namespace.
The . notation's use with the prototype is one specific instance of accessing properties on a specific type of object (the prototype). A prototype is used on a function object and has a very specific use when creating new instances of that function.
function foo() {
}
foo.prototype.talk = function() {
alert("hello");
}
var y = new foo();
y.talk();

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 :)

Object literal as prototype

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 :)

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.

Categories

Resources