This question already has answers here:
Literal notation VS. constructor to create objects in JavaScript [duplicate]
(2 answers)
Closed 9 years ago.
For creating Javascript object, we can use Literal or Constructor way;
In Constructor way, we say;
function myObj(){
this.myProp1 = "abc";
this.myProp2 = "xyz";
}
In literal way, we say;
var myObj = {
myProp1:"abc",
myProp2:"xyz",
}
My question is when declaring properties, why there is a difference like why do we use "this.myProp1" in case of Constructor way and not use "this" in Literal way ?
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 myObj, but nothing else happens. methodOne and methodTwo don't exist until myObj is explicitly called.
Depending on how myObj is called, the methods methodOne and methodTwo will end up in different places:
myObj():
Since no context is supplied, the this defaults to window and the methods will become global.
var app1 = new myObj():
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, myObj.methodOne remains undefined.
myObj.call(yourApp):
This calls my myObj but sets the context to be another object, yourApp. The methods will get assigned to yourApp, overriding any properties of yourApp 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 methodOne and methodTwo 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 myObj = function(){
var variableOne = "ABCD1234";
this.methodOne = function(){
// Do something with variableOne
console.log(variableOne);
};
this.methodTwo = function(){
// Do something else with variableOne
};
};
myObj();
alert(variableOne); // undefined
alert(myObj.variableOne); // undefined
If you wanted to make variableOne exposed (public) you'd do:
var myObj = function(){
this.variableOne = "ABCD1234";
this.methodOne = function(){
// Do something with variableOne
console.log(this.variableOne);
};
this.methodTwo = function(){
// Do something else with variableOne
};
};
myObj();
alert(variableOne); // undefined
alert(myObj.variableOne); // ABCD1234
When defining something literally, the object is being built directly in the code. It doesn't exist yet until it is complete. At that point, this would have no meaning (not that there is any need for it either).
To understand this in the object creation function, first realize that this is special in JavaScript. Whenever you call a function, you can pass anything you want to be this. In general, things like event handlers will pass the event-causing DOM object to be passed as this. In your code, you do this as: MyFunction.call(whatever_needs_to_be_this[, param0, param1]);. When you use the new operator, such as var mything = new SomeThing();, JavaScript is essentially doing something like:
var mything = {};
SomeThing.call(mything);
this in this case is going to be mything in your function.
Related
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();
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 :)
This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Prototyped and a non-prototyped method? [duplicate]
(1 answer)
Closed 8 years ago.
Suppose I create an object in javascript.
var myObject = {};
What is the difference between...
myObject.someFunc = function(){...};
and
myObject.prototype.someFunc = function(){...}
in javascript?
I am having trouble understanding the difference or if there is a difference and how and when to use either of these syntaxes.
It seems when I code something like this that there really is no difference.
I am looking for both a client side (browser) and server side (like node.js) answers.
I want to code properly and accurately and this is really bothering me.
In this case:
var myObject = {};
myObject.someFunc = function(){...};
All you're doing is creating a plain object, which happens to have a property which is a reference to a function. This is often done just for name spacing, i.e. to group a whole load of functions in one place under a common object.
Note however that var myObject = {} doesn't actually have a prototype so your second example is impossible.
For an object to have a prototype it must be the result of a constructor function, i.e.
function MyObject() {
...
}
MyObject.prototype.someFunc = function() { }
var myObject = new MyObject();
// myObject.someFunc can now be used
The prototype is a property of the constructor function - not of any instance of that class.
If you put the function on the prototype only one instance of the function object exists and will be shared by all instances of the class. This is more memory efficient that having a copy on each instance.
All of this applies regardless of whether the code is in a browser or on a server - it's still the same language.
Essentially this represents a static method (or a method attached to only that object (myObject in this case):
myObject.someFunc = function () {...};
This represents a method attached to the prototype of the object (an instance method):
myObject.prototype.someFunc = function () {...};
myObject.someFunc = function(){...} is a one time instance of that function, who's return value is being assigned to the someFunc property of myObject.
myObject.prototype.someFunc = function(){} is actually creating a method that can be called anywhere on myObject and will change the same instances of values each time.
myObject.prototype.someFunc = function(num){
this.num_to_be_stored = num;
}
will change the value of num_to_be_stored not someFunc which is what is happening in the first instance.
edit: sorry early morning was not clear on what I was trying to say.
I recently started programming JavaScript and thought everything would be good...
Well today I faced a problem I can't solve on my own.
My tutorial/ learning project has a class called model. In this class there are several private and one public variable. This variable is of type CustomEvent:
function Model(){
/**
* Array in which the questions are stored
*/
var questions=new Array();
var db;
var valuesSplit="*";
var tableName="quests";
this.myEvent=new CustomEvent("my event");
So as you can see "myEvent" is public and can be called from outside. In this case it is an event which can be subscribed (this is done outside this class by other objects that want to listen) and it can be fired (this is done in the same class). And this is my problem.
How can I access myEvent within the model class?
I tried:
this.myEvent.fire()
and:
myEvent.fire()
But I always get "myEvent is not defined".
Probably the first thing to say is: JavaScript doesn't have classes. The sooner you stop thinking of "JavaScript classes," the better off you'll be. :-) JavaScript has OOP, but not the kind with classes. Your Model function is called a constructor function.
You can access myEvent from any code that has a reference to the object created by new Model, which includes code in your constructor (via this — e.g., the way you're setting it up) and any function called with this referring to that object (or, of course, "externally" via someObjReference.myEvent).
So probably this.myEvent.fire() is what you want, but the code you're calling it from doesn't have the right this value. That's because in JavaScript, this is controlled entirely by how a function is called, not where the function is defined as it is in some other languages. See my blog articles Mythical methods and You must remember this for more details, but I've done a somewhat truncated discussion below.
Here's an example of a fairly standard way to set up a constructor function with useful methods that all instances share:
function Foo() {
this.myEvent = new CustomEvent("my event");
}
Foo.prototype.bar = function() {
this.myEvent.fire();
};
// Usage:
var f = new Foo();
f.bar(); // Fires the event indirectly, via the code in `bar`
f.myEvent.fire(); // Fires it directly
Note that that only works if bar is called with this referring to an object with a myEvent property. It's easy to call bar with this set to something else entirely:
document.getElementById("someID").onclick = f.bar;
When the click occurs, the bar function gets called, but this does not refer to an object created via Model. (It will refer to the element with the id "someID" instead.) And so this line in bar
this.myEvent.fire();
...will fail.
If you're used to class-based languages, you can see how this is totally different from, say, Java, C#, or C++. In those langauges, this inside bar will always refer to an object created via new Model. Not so JavaScript, which is both awkward and powerful.
This flexibility of functions (not being bound to any particular object) is one of the biggest things to get used to, and take advantage of, in JavaScript. The other is how functions are closures, which is powerful but not complicated.
So if this is set by how a function is called, how do you do that? There are two ways:
Call the function by referencing it from an object property in the same expression as the call. That's an awkward way of saying do this:
var f = new Foo();
f.bar(); // <== The key bit
f["bar"](); // <== Also works
The expression f.bar() does two things, which interact: The first thing it does is retrieve the property bar of the object referenced by f, and get that property's value (which is a function reference). Then it calls that function (because of the ()). The way JavaScript works, because you did those two things in the same overall expression, the interpreter sets this to f during the call to bar for you. But note this key distinction:
var f = new Foo();
var b = f.bar;
b(); // <== Different!
Now when the bar function gets called, this will not be set to f (it'll be set to the global object, which is window on browsers), because we've separated the property retrieval from the function call.
Alternately, you can use the built-in features of JavaScript function objects, their call and apply functions. call and apply do exactly the same thing, the only difference between them is how you supply the arguments for the function. Example:
var f = new Foo();
f.bar(1, 2): // <== Calls `bar` with `this` === `f` and passing in
// the arguments 1 and 2
var b = f.bar;
b.call(f, 1, 2); // <== Does the same thing as f.bar(1, 2)
var args = [1, 2];
b.apply(f, args); // <== Does the same thing as f.bar(1, 2)
E.g., call and apply allow you to set what this should be explicitly when you call the function. The only difference between them is that call accepts the arguments to give the function as further arguments to call, and apply accepts them as an array.
If you want to use myEvent in a non public function in your Model than you have to create another reference to the myEvent which isn't using the this reference of your Model. Because the this in another function is something else than in your Model function. The easiest way to bypass this problem is if you define a new variable in your Model:
var that = this;
Then you can call your myEvent like:
that.myEvent
The myEvent member should be visible both in the inner & outer scope of the object :
function Model(){
this.myEvent = 'some value';
this.canAccessEvent = function(){
return 'myEvent' in this;
}
}
var m = new Model();
// access from outside :
alert(m.myEvent);
// access from inside :
alert('Model can access the even? ' + m.canAccessEvent());
However, it is very possible that your new CustomEvent function doesn't exist or does not return a valid object making your myEvent variable to be undefined. I suggest you attribute some other value to the myEvent property and see if it is defined. If it is defined, then the problem lies in your CustomEvent function.
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.