I am new to Javascript and now studying it...
var person = function() {
this.name = "name"
};
var person2 = function() {
var obj = {};
obj.name = "name";
return obj;
};
Let's suppose we have two functions shown above. It seems that objects can be created by using either of the functions. For example)
var p = new person();
var p2 = new person2();
My question is: What's difference between person vs person2? Are they exactly the same? If not which one is a more preferable way to use?
Thanks
The normal way of creating an object is the first way.
The second way will create two objects, and one will be discarded. One object will be created before the function is called, just as with the first method, but because the function returns another object the first object will be discarded and the returned object will be used instead.
An important difference between the methods is that the second one can't use a prototype. Anything that you put in the prototype of the function will be applied to the object that ends up being discarded.
The difference is in the way you use the functions.
The first one is intended to be used as a constructor, this being set to the newly created object. It is intended to be used in combination with the operator new, as follows:
var bill = new person();
This is just like a normal constructor as in typical OOP language.
The second one is intended to be used as a normal function (without new), e.g.:
var bill = person();
You can use this way of object creation in combination with the builder pattern.
Related
I am learning and trying to understand JavaScript Objects deeply. I learnt Object prototype via example below.
var MyObj = function(){
this.Name = "Stackoverflow";
}
MyObj.prototype.prop = "OK";
var instance = new MyObj();
instance.prop = "OK";
console.log(instance.hasOwnProperty("Name")); //true
console.log(Object.getOwnPropertyNames(instance)); //[ 'Name', 'prop' ]
In the example above, instance object can not access getOwnPropertyNames of Object. Because getOwnPropertyNames function is not a member of prototype of Object. Following this, when i write my own object like Object above e.g.
var MyDream = function(){}
MyDream.prototype.canAccessThisMethod = function(x){};
var instanceSample = new MyDream();
instanceSample.canAccessThisMethod("blabla"); //because of prototype
MyDream.method(blabla); // didn't work.
How to make MyDream.method work in this example?
Apart from explaining the prototypes, let us focus on the thing you asked in following snippet i.e.
var MyDream = function(){}
MyDream.prototype.canAccessThisMethod = function(x){ };
var instanceSample = new MyDream();
instanceSample.canAccessThisMethod("blabla"); //because of prototype
MyDream.method(blabla); //How can we write "MyDream.method" in this example
Let us go step by step.
var MyDream = function(){}
You created an anonymous function and assigned it to MyDream variable. Functions are first class objects in JavaScript. They are powerful and flexible. So being a first class object you can assign them to variables like you did. You can pass them as parameters. On top of that you can also extend there prototype chain as
MyDream.prototype.canAccessThisMethod = function(x){ };
I believe you have figured out the rest of the stuff so skipping the details and on fast forward moving to this statement.
MyDream.method(blabla);
Unfortunately, this will not work. The reason being, to add a function as method you need to assign it as function literal. You can add methods to function just like Objects.
MyDream.method = function(x) {
console.log(x);
}
MyDream.method("bla bla");
You can do this, for example:
instanceSample.prototype.method = function( x ){
...
}
Prototype means that the method "method" will be added to all objects of the class "MyDream"
Since my last question, I've been studying Javascript's prototype model and trying to get rid of the OOP vision I inherited from other languages (pun slightly intended).
I went back to basics and read Crookford's Javascript: The Good Parts, along with You Don't Know JS material and decided to stick with the so called behaviour delegation.
Restructuring my previous example implementing behaviour delegation and namespacing, I wrote:
var GAME = {};
(function(namespace) {
var Warrior = {};
Warrior.init = function(weapon) {
this.setWeapon(weapon);
};
Warrior.getWeapon = function() {
return this.weapon;
};
Warrior.setWeapon = function(value) {
this.weapon = value || "Bare hands";
};
namespace.Warrior = namespace.Warrior || Warrior;
})(GAME);
(function(namespace) {
var Archer = Object.create(namespace.Warrior);
Archer.init = function(accuracy) {
this.setWeapon("Bow");
this.setAccuracy(accuracy);
};
Archer.getAccuracy = function() {
return this.accuracy;
};
Archer.setAccuracy = function(value) {
this.accuracy = value;
};
namespace.Archer = namespace.Archer || Archer;
})(GAME);
So, everytime I copy a new Archer object:
var archer1 = Object.create(GAME.Archer);
only this object will be created, conserving memory.
But what if I don't want to expose "accuracy" attribute? The attribute would only increase by calling a "training()" method or something similar. I tried to use var accuracy inside the anonymous function, but it turns into kind of static variable, all instances of Archer would share the same value.
The question: Is there any way to set a variable as private while still keeping behaviour-delegation/prototypal pattern?
I do know of functional pattern as well, Here I succesfully achieved variable privacy, at the cost of memory. By going functional, every new "archer" instance generates a new "Warrior" and then a new "Archer". Even considering that Chrome and Firefox have different optmizations, testings on both report that the Delegation/Prototypal pattern is more efficient:
http://jsperf.com/delegation-vs-functional-pattern
If I go with the pure-object delegation pattern, should I just forget the classic encapsulation concept and accept the free changing nature of properties?
I would try to answer your question with something that is slightly different then this one that tells you how to use a library.
Different in that it will(hopefully) give you some ideas of how can we tackle the problem of private vars in OLOO ourselves. At least to some extent, with our own code, no external lib needed, which could be useful in certain scenarios.
In order for code to be cleaner I've striped your anonymous wrapper functions, since they are not related to problem in any way.
var Warrior = {};
Warrior.warInit = function (weapon){
this.setWeapon(weapon);
}
Warrior.getWeapon = function(){
return this.weapon;
}
Warrior.setWeapon = function (value){
this.weapon = value || "Bare hands";
}
var Archer = Object.create(Warrior);
Archer.archInit = function (accuracy){
this.setWeapon("Bow");
this.setAccuracy(accuracy);
}
Archer.getAccuracy = function (pocket) {
return pocket.accuracy;
}
Archer.setAccuracy = function (value, pocket){
pocket.accuracy = value;
}
function attachPocket(){
var pocket = {};
var archer = Object.create(Archer);
archer.getAccuracy = function(){
var args = Array.prototype.slice.call(arguments);
args = args.concat([pocket]);
return Archer.getAccuracy.apply(this, args)
};
archer.setAccuracy = function(){
var args = Array.prototype.slice.call(arguments);
args = args.concat([pocket]);
return Archer.setAccuracy.apply(this, args);
};
return archer;
}
var archer1 = attachPocket();
archer1.archInit("accuracy high");
console.log(archer1.getAccuracy()); // accuracy high
archer1.setAccuracy("accuracy medium");
console.log(archer1.getAccuracy()); // accuracy medium
Test code above here. (and open your browser console)
Usage
1 ) General practice in OLOO about naming functions on different levels of prototype chain is apposite from OOP. We want different names that are more descriptive and self documenting, which brigs code that is cleaner and more readable. More importantly, by giving different names we avoid recursion loop:
Archer.init = function(accuracy, pocket){
this.init() // here we reference Archer.init() again, indefinite recurson. Not what we want
...
}
Archer.archInit = fucntion (accuracy, pocket){ // better,
this.warInit() // no name "collisions" .
}
2 ) We've created an attachPocket() function that creates internal variable pocket. Creates new object with Object.create() and sets it's prototype to point to Archer. Pause. If you notice, functions that required a private var we have defined so that each of them take one more parameter(pocket), some use just pocket. Here is the trick.
By making wrapper functions like archer.setAccuracy(), archer.getAccuracy()
... we can create closures and call directly functions that need
private var (here pocket) and pass it to them as an argument.
Like so:
function AtachPocket(){
...
var pocket = {};
archer.setAccuracy = function(){
var args = Array.prototype.slice.call(arguments);
args = args.concat([pocket]); // appending pocket to args
return Archer.setAccuracy(this, args);
};
...
}
Essencially by doing this we are bypassing what would have been a normal search for functions in prototype chain, just for functions that have need for a private var. This is what "call directly" refers to.
By setting the same name for a function in archer("instance") like it is in prototype chain (Archer) we are shadowing that function at the instance level. No danger of having indefinite loops, since we are "calling directly" like stated above. Also by having the same function name we preserve the normal, expected behaviour of having access to same function in an "instance" like it is in a prototype chain. Meaning that afther var archer = Object.create(Archer) we have access to function setAccuracy like we would if it had been normal search for function in prototype chain.
3 ) Every time attachPocket() is invoked it creates a new "instance" that has those wrapper functions that pass a pocket argument (all as an internal detail of implementation). And therefore every instance has own, unique, private variable.
You would use functions in an "instance" normally:
archer1.archInit("accuracy high"); // Passing needed arguments.
// Placed into pocked internally.
archer1.getAccuracy(); // Getting accuracy from pocket.
Scalability
Up to now all we have is function that "attaches a pocket" with hardcoded values like Archer.setAccuracy, Archer.getAccuracy. What if we would like to expand prototype chain by introducing a new object type like this var AdvancedArcher = Object.create(Archer), how the attachPocket is going to behave if we pass to it AdvancedArcher object that might not even have setAccuracy() function? Are we going to change attachPocket() each time we introduce some change in prototype chain ?
Let's try to answer those questions, by making attachPocket() more general.
First, expand prototype chain.
var AdvancedArcher = Object.create(Archer);
AdvancedArcher.advInit = function(range, accuracy){
this.archInit(accuracy);
this.setShotRange(range);
}
AdvancedArcher.setShotRange = function(val){
this.shotRange = val;
}
More generic attachPocket.
function attachPocketGen(warriorType){
var funcsForPocket = Array.prototype.slice.call(arguments,1); // Take functions that need pocket
var len = funcsForPocket.length;
var pocket = {};
var archer = Object.create(warriorType); // Linking prototype chain
for (var i = 0; i < len; i++){ // You could use ES6 "let" here instead of IIFE below, for same effect
(function(){
var func = funcsForPocket[i];
archer[func] = function(){
var args = Array.prototype.slice.call(arguments);
args = args.concat([pocket]); // appending pocket to args
return warriorType[func].apply(this, args);
}
})()
}
return archer;
}
var archer1 = attachPocketGen(Archer,"getAccuracy","setAccuracy");
archer1.advInit("11","accuracy high");
console.log(archer1.getAccuracy()); // "accuracy high";
archer1.setAccuracy("accuracy medium");
console.log(archer1.getAccuracy());
Test the code here.
In this more generic attachPocketGen as first argument we have a warriorType variable that represents any object in our prototype chain. Arguments that may fallow are ones that represent names of functions that need a private var.
attachPocketGen takes those function names and makes wrapper functions with same names in archer "instance". Shadowing, just like before.
Another thing to recognise is that this model of making wrapper functions and using apply() function to pass variables from closures is going to work for functions that use just pocket, functions that use pocket and other variables, and when ,of course, those variables use the relative this reference in front of them.
So we have achieved somewhat more usable attachPocket, but that are still things that should be noticed.
1) By having to pass names of functions that need private var, that usage implies that we(attachPocketGen users) need to know whole prototype chain (so we could see what functions need private var). Therefore if you are to make a prototype chain like the one here and just pass the attachPocketGen as an API to the programmer that wants to use your behaviour-delegation-with-private-variables, he/she would had to analyse objects in prototype chain. Sometimes that is not what wee want.
1a) But we could instead, when defining our functions in prototype chain (like Archer.getAccuracy) to add one property to them like a flag that can tell if that function have need for a private var:
Archer.getAccuracy.flg = true;
And then we could add additional logic that checks all functions in prototype chain that have this flg and fills the funcsForPocket.
Result would be to have just this call:
var archer1 = attachPocketGen(AdvancedArcher)
No other arguments except warriorType. No need for user of this function to have to know how prototype chain looks like, that is what functions have need for a private var.
Improved style
If we are to look at this code:
Archer.archInit = function (accuracy){
this.setWeapon("Bow");
this.setAccuracy(accuracy);
}
We see that it uses "pocket" function setAccuracy. But we are not adding pocket here as last argument to it because setAccuracy that gets called is shadowed version, the one from instance. Becouse it will be called only from an instance like so archer1.archInit(...) That one is already adding a pocket as last argument so there is on need to. That's kinda nice, but the definition of it is:
Archer.setAccuracy = function (value, pocket){ ...
and that can be confusing when making objects in prototype chain like Archer.archInit above. If we look the definition of setAccuracy it looks like we should it. So in order not have to remember that we don't have to add pocket as last arg in functions (like archInit) that use other pocket functions, maybe we should to something like this:
Archer.setAccuracy = function (value){
var pocket = arguments[arguments.length -1];
pocket.accuracy = value;
}
Test the code here.
No pocket as last argument in function definition. Now it's clear that function doesn't have to be called with pocket as an argument wherever in code.
1 ) There are other arguably minor stuff to refer to when we think about more general prototype chain and attachPocketGen.Like making functions that use pocket callable when we dont wan't to pass them a pocket, that is to toggle pocket usage to a function, but in order not to make this post too long, let's pause it.
Hope this can give you view ideas for solution to your question.
Here is my superclass:
function Element() {
var name;
this.setName(n) = func()...{};
this.getName() = func()..{return name};
}
My another child class:
Select = null;
...
Select =
function (n) {
if (typeof n !== "undefined")
this.setName(n);
...
}
Select.prototype = new Element();
Select.prototype.constructor = Select;
So, what kind of "weird moment" am I talking about? Here it is:
var e1 = new Select("element1");
e1.getName(); // return "element1"
var e2 = new Select(); // WITHOUT NAME
e2.getName(); // return "element1"!!! should be ""!
This is a fairly predictable behavior, but how to get around this?
Of course, i can make something like a this.clear() in Element, that will clear properties and put this method in Select function, but maybe there is a proper solution?
You should add this line Element.call(this, n) into Select. It's quite hard to explain and I feel grumpy because I don't like fake private properties in javascript, but well, I must provide some details in order for you to understand what you are currently doing, otherwise I will not be able to get to sleep.
So, doing new Element() creates a new context where name can live without disturbing anyone. Additionally, two new functions called setName and getName are created, and bound to the prototype object of Select.
From now on, if you create a new instance of Select, you can call these functions since they are available in the prototype of the instance. This actually happens doing new Select("element1"). Indeed, n is defined, so, setName is called from this, which refers to the instance.
But most importantly, calling setName with n set to "element1" will also set name to "element1". Then, if you create a second instance of Select, without defining n, setName is not called, so, name remains set to "element1", for both instances.
Why for both instances? Because both instances share the same setName method, the one bound to the prototype, and this method refers to a unique name variable - remember that Element was called only once.
Finally, why this new line Element.call(this, n) prevents name from being shared? Because each call to Element creates a new context, that is to say, a new name, a new setName and a new getName, and binds these two methods to the newly created instance.
Well, hope this is the morning for you, I would be sorry if you get into sleeping disorders by my fault...
As mentionned by Bergi and HMR, this way of creating the prototype - Child.prototype = new Parent - is out of fashion and will lead you to a dead end. Keep in mind that the prototype is kind of a template for creating instances. Knowing this and considering your code, we can make at least two observations :
As you know, a constructor is intended to initialize instances. In your case, the initialization process - what's inside Element - is unnecessarily executed since the goal is currently to set the template upon which instances will be created.
Let's say that name is required in new Element(name), otherwise your program crashes. What kind of name would you give to the prototype? This question is obviously useless, since you would not want to give a name to a template.
To bypass these problems you need a middleman as shown in the below code (copied from the link shared by Bergi). As you can see, the creation of the prototype is delegated to a "dummy" constructor which is empty. Doing so allows to resolve the two problems raised above.
function Dummy () {}
Dummy.prototype = Element.prototype;
Select.prototype = new Dummy();
Select.prototype.constructor = Select;
Alternatively, you could use the built-in Object.create() :
Select.prototype = Object.create(Element.prototype);
Select.prototype.constructor = Select;
Further reading :
https://stackoverflow.com/a/15461601/1636522
http://aaditmshah.github.io/why-prototypal-inheritance-matters/
You should use the prototype of Element so the variables are not shared between the instances:
function Element() {}
Element.prototype.setName = function(n) { this.name = n; };
Element.prototype.getName = function() { return this.name; };
In this case e2.getName() will return undefined.
I've written a JS object that obfuscates email addresses, however I've discovered two slightly different ways of doing so (each with 1 private method and 1 public method):
Object 1:
var email = new function()
{
function encrypt(code, key)
{
<eliminated for brevity>
};
this.mailto = function(address, name)
{
link = encrypt(<code>, <key>);
document.write(''+ name +'');
}
};
Object 2:
var email = function()
{
function encrypt(code, key)
{
<eliminated for brevity>
};
return {
mailto: function(address, name)
{
link = encrypt(<code>, <key>);
document.write(''+ name +'');
}
};
}();
Both of these syntaxes work and can be called with:
email.mailto('example', 'Example');
I'm particularly interested in memory usage or extensibility.
It looks to me as if Object 1 would create a new instance every time it's called?
What are the differences?
It looks to me as if Object 1 would create a new instance every time it's called?
No. You're doing this with the new keyword already (and once only), email is a static object.
What are the differences?
The first email object does inherit from an extra prototype object that is not apparent in the code. Yet, it does e.g. store the initialisation function, making it non-anonymous. You could create another instance of your module by
var email2 = new (email.constructor)();
This is completely superfluous and probably unintentional.
I'm particularly interested in memory usage
The first option does have an additional prototype object and needs to hold the constructor function in memory, while the second one can garbage-collect the IEFE after it was used. Use the second pattern only, avoid the first one.
This is just a simple question. Either way works. I prefer my first example, but I didn't know if doing it this way causes more memory to be allocated than the second example since we are calling "new" on the object....
Example 1
var post = function(){
var self = this;
self.div = $('<div></div>');
self.color = function(color){
this.div.css({background:color});
}
}
var p = new post();
p.color("#FFF");
Example 2
var post = function(){
self = this;
self.div = $('<div></div>');
}
var color = function(p, color){
p.div.css({background:color});
}
var p = new post();
color(p, "#FFF");
So, in the first example, the color function I believe will get recreated everytime a new post is called. What if I have a 100 new post(); calls. Is is less efficient than Example 2 where the function is only defined one time?
Does that make sense what I'm asking?
Yes, in Example 1 there will be a separate instance of the "color" function for every instance of a "post" object, whereas there will only be one instance of the function in Example 2. Clearly, if you plan to have a large number of "post" object instances then you are using more memory than you need to.
In JavaScript, the typical (or prototypical!) way of solving this problem using the best parts of your two examples is as follows (note that I am using "Post" with a capital "P", per convention of constructor functions which are intended for use with the new operator):
function Post() {
this.div = $('<div></div>');
}
Post.prototype.color = function(color) {
this.div.css({background:color});
}
var p = new Post();
p.color("#FFF");
When looking for a property on an object (e.g. "p.color" in our examples), if the property isn't defined directly on the instance then it is looked up as an attribute of the "prototype" of the function which constructed the object (e.g. "Post.prototype.color"). This also means you can define instance methods on the prototype and override them by assigning new functions on individual instance property names directly, if you want.
This way we still get the nice object-oriented syntax of calling "p.color(...)" and the benefit of only one function method instance which is shared by all "Post" instances.