This question already has answers here:
Defining methods via prototype vs using this in the constructor - really a performance difference?
(7 answers)
Closed 9 years ago.
I want to learn the advantages of using JavaScript prototype. Object prototype usage is increasing performance.
I want to see this by usage of memory.
Case-1
var Foo1 = function (name) {
this.name = name;
getFirstName = function() { return "name1"; };
getLastName = function() { return "name2"; };
};
for (var i = 0; i < 1000; i++) {
var foo1 = new Foo1();
}
Case-2
var Foo2 = function (name) {
this.name = name;
};
Foo2.prototype = {
getFirstName: function () { return "name1"; },
getLastName: function () { return "name2"; },
};
for (var i = 0; i < 1000; i++) {
var foo2 = new Foo2();
}
which case is using memory more than another?
Can I learn memory usage of cases?
What is the difference about memory usage of cases?
If you define a function or an object to belong to the prototype then it's shared by all instances and creating an object with new does not create it's own instance of the function/object. In this sense defining something to belong to the prototype uses less memory. The precise difference would be that case 1 (look at comments below because your definition is not proper) would create 1000 instances of each function. Case 2 (again look at the comments below) would create only 1 instance of each function.
However case 2 is not defining in the prototype. You're essentially redefining the prototype there. The correct usage would be:
function Foo2 (name) {
this.name = name;
};
Foo2.prototype.getFirstName = function () { return "name1"; };
Foo2.prototype.getLastName = function () { return "name2"; };
Your case 1 is also not correctly defined in terms of what you're trying to achieve because getFirstName and getLastName are not defined through this (the instance).
The second case is more memory-efficient and performant. When you define methods in the constructor then the same functions or methods are allocated for each object so the object consumes more memory. So define methods in the prototype-object then all objects share the same methods only once.
So my advice is that you define attributes (number,string...) in the constructor and methods or functions in the prototype-object like you did it in the second case.
By the way when you define an object this way:
var Foo1 = function (name) {
this.name = name;
getFirstName = function() { return "name1"; };
getLastName = function() { return "name2"; };
};
The method getFirstName and getLastName are properties of window, because you actually write this:
var Foo1 = function (name) {
this.name = name;
window.getFirstName = function() { return "name1"; };
window.getLastName = function() { return "name2"; };
};
Related
http://jsfiddle.net/F5ZSA/1/
Here's the code from above fiddle:
"use strict";
function Human()
{
this.myname;
this.things = [];
this.addThing = function(string)
{
this.things.push(string);
}
this.getThings = function()
{
return this.things;
}
this.setName = function(name)
{
this.myname = name;
}
this.getName = function()
{
return this.myname;
}
}
Mister.prototype = new Human();
function Mister()
{
}
var mister1 = new Mister();
var mister2 = new Mister();
mister1.setName("Peter");
mister2.setName("Steven");
mister1.addThing("mister1 reporting");
mister2.addThing("mister 2 reporting");
console.log(mister1.getName());
console.log(mister2.getName());
console.log(mister1.getThings());
console.log(mister2.getThings());
When you run it, the result suggests that 'myname' property is different for each Mister instance, while 'things' property seems to be shared between all instances. Is it suppose to be like that? If yes, what is the general rule telling which prototype properties are shared among 'inheriting' objects?
Coming from other OOP languages, my intuition was that every object should have a separate prototype instance. Is it a good idea to try to enforce it in js?
This is the classic problem when coming from traditional OOP languages. By creating the new object the prototype is copied. The keyword 'this' already refers to new object, but the reference to another object from the prototype as yours this.things refers still to the same space in the memory. When you create two objects you create two references to the same object (in this case array)
the following will work as you would expect. To go around the 'this' issue i put there the init method called to initialise the object, in this case to create multiple array objects, each for new object Mister.
var Human = function()
{
this.myname;
this.things;
this.things;
return {
addThing:function(string)
{
this.things.push(string);
},
getThings:function()
{
return this.things;
},
setName: function(name)
{
this.myname = name;
},
getName: function()
{
return this.myname;
},
init: function(){
this.things = new Array();
}
}
}
var Mister = function(){}
Mister.prototype = new Human();
var mister1 = new Mister();
var mister2 = Object.create(Mister.prototype);
mister1.init();
mister2.init();
mister1.setName("Peter");
mister2.setName("Steven");
mister1.addThing("mister1 reporting");
mister2.addThing("mister 2 reporting");
console.log(mister1.getName());
console.log(mister2.getName());
console.log(mister1.getThings());
console.log(mister2.getThings());
I'd like to have an object with multiple levels of methods and properties. The top level will have properties and methods. Some of these properties will then act as name-spaces for second level methods and properties.
e.g.
//first level methods
base.doStuff();
base.doMore();
//second level methods
base.level2.doStuff();
Doing the first level is straight forward:
function Base(foo) {
this.foo = foo;
}
Base.prototype.doStuff = function () {
console.log(this.foo);
}
Base.prototype.doMore = function () {
console.log(this.foo);
}
base = new Base("bar");
base.doStuff();
Is it possible to get a second level, where in the function expression the "this" keyword points back to the Base constructor?
It's much easier to do this without prototypes:
function Base() {
var base = this;
base.level2 = {
moreStuff: function() {
// use "base" instead of "this" here
}
};
}
This can be combined with either prototypical methods, as in your example, or methods defined directly on base in the constructor. The downside of this is that you are creating the method functions every time you instantiate a new object, so you miss some of the shared-prototype goodness of standard prototypical methods.
You could create a new prototype-based object to be your level2:
function Level2() {}
Level2.prototype.moreStuff = function() {
// do stuff
}
function Base() {
this.level2 = new Level2();
}
But the methods of base.level2 won't be bound to base unless you bind them explicitly. Various libraries have bind support (e.g. Underscore's _.bind), or you can do it in plain JS:
function Base() {
var base = this;
base.level2 = new Level2();
base.level2.moreStuff = function() {
return Level2.prototype.moreStuff.apply(base, arguments);
}
}
You could further simplify here, but you're always going to have to make new methods bound in one way or another, because JS is never going to assign this in base.level2.moreStuff() to base without explicit binding - so in most cases the first option is the easiest and cleanest.
But really, is it worthwhile just for namespacing? If there's no functional value, it's a lot harder than simply calling your methods level2MoreStuff(), etc.
Well,
base.doStuff();
is calling doStuff in context of base. It is the same as
base.doStuff.call(base);
You can call and apply any function, for overriding this:
var base = new Base();
var someFun = function () {
console.log (this === base); // true
};
someFun.call(base);
Further anonymous example:
var anObj = {
method0: function () {
console.log (this === anObj); // true
}
};
anObj.method1 = function () {
console.log (this === anObj); // true
};
anObj.method0();
anObj.method1();
So the "second level" points this to level2, not to the "first level" object.
This is a really bad idea, but here goes:
function Base() {
this.name = 'Base';
this.level2 = new Level2(this);
}
Base.prototype.whatsMyName = function(){
alert(this.name);
};
function Level2(base) {
this.name='Level2';
for(var func in Level2.prototype) {
this[func] = Level2.prototype[func].bind(base);
}
}
Level2.prototype.whatsMyName = function(){
alert(this.name);
};
var b = new Base();
b.whatsMyName(); //Base
b.level2.whatsMyName(); //Also Base
You can see it running here: http://jsfiddle.net/zLFgd/1/
I am trying to understand what is going on here:
if (!Object.create) {
Object.create = (function () {
var F = function(){};
return function (o) {
if (arguments.length !== 1) {
throw new Error('Object.create implementation only accepts one parameter.');
}
F.prototype = o;
return new F();
};
}());
}
what does F.prototype mean... How does returning a function work
These are two separate questions. The concept of a prototype and what it means is separate from the concept of returning functions. I will do my best to try and explain.
What does F.prototype mean?
Javascript does not support inheritance in the classical sense, but rather uses prototype inheritance to pass object properties from one function to another.
All Javascript objects contain a prototype field by default. The prototype field is always initially set to the base Object object. (You can create a new instance of Object by doing
var x = new Object() or by doing var x = {}.) You can create objects that set the prototype to another object thereby gaining access to their methods and properties that are placed on the prototype.
Let's walk through an example to illustrate.
Consider you create a constructor to create a Bird object.
function Bird(name) {
var me = this;
this.name = name;
this.flying = false;
this.fly = function() { me.flying = true; };
}
Bird.prototype.fly = function() { this.flying = true; }
Bird.prototype.land = function() { this.flying = false; }
If we look at the details of this object (which you can do using console.dir(obj), or by using Chrome developer tools):
Now consider you want to create another bird object that implements the Object Bird. You would do something like this.
function Duck(name) {
this.name = name;
this.quack = function() {
console.log("quack");
}
}
If you look at the details of this object you see:
Now if you want to make the duck fly, you do not have a method on it yet. You need to set the prototype of Duck to be Bird. You do that by doing something like this:
function Duck(name) {
this.name = name;
this.quack = function() {
console.log("quack");
}
}
Duck.prototype = new Bird();
Now when you look at the details of the object you will see that the prototype is now set to bird.
In short prototypes are used to provide code reuse among objects. Programmers coming from object oriented backgrounds can use prototypes to provide the same mechanisms as inheritance. Mozilla has a good article that goes into more depth.
How does returning a function work?
Javascript is a functional programming language. One of the principles of the functional programming paradigm is the existence function as first class objects. Among other things this means that functions are treated the same as any other object.
A function returning a function means nothing different then a function that returns a string.
function getString() {
return "I am a string";
}
You can use the result of this function in whatever way you choose. A function that returns a function is the same way.
function getFunctionToGetSomethingImportant() {
return function() {
return "I am something important";
}
}
Now when you want to get a function that returns a function that does something important you can do this:
var x = getFunctionToGetSomethingImportant();
x();
Despite these use cases having little value, using functions as first class objects is incredibly valuable. Functions can be treated like other objects which means they can be passed into other functions as parameters (a concept called higher order functions).
function filter(list, function(element) {
return element < 0;
});
The function filter takes as its second parameter a function that takes an element parameter. An implementation of filter would loop through each element in list and apply the function given as the second paramater. This is one example of many important use cases of functions as first class objects. This wiki article contains more information.
Initialy F is empty function and new F() returns empty object, i.e {}
after
F.prototype = o
F as class gets properties of the object o
for example if o={a:1}, then new F() returns {a:1}
this is the same like you define F as
F = function(){
this.a = 1;
}
but in your example you can create new object based on the class of object o passed to the create() function
function dostuff() {
return function () {console.log('hello')}
}
f = dostuff();
f();
--output:--
hello
.
Array.prototype.greet = function() {console.log('hello')};
[1, 2, 3].greet();
--output:--
hello
.
function Dog(name) {
this.name = name;
this.speak = function() {console.log('Ruff, ruff!') };
}
mydog = new Dog("Joey")
console.log(mydog.name);
mydog.speak();
--output:--
Joey
Ruff, ruff!
.
function Dog() {
}
Dog.prototype.speak = function() {console.log("Ruff, ruff!")};
mydog = new Dog();
mydog.speak();
--output:--
Ruff, ruff!
.
function Dog() {
}
var obj = {
name: "Joey",
speak: function() {console.log("Ruff, ruff!")}
}
Dog.prototype = obj;
mydog = new Dog();
console.log(mydog.name);
mydog.speak();
--output:--
Joey
Ruff, ruff!
obj.jump = function() {console.log("Look at me jump!")};
mydog.jump();
--output:--
Look at me jump!
.
var F = function() {
};
var o = {
"greet": function() {console.log('hello')}
};
F.prototype = o;
f = new F();
f.greet();
--output:--
hello
Lets say I have this class:
function classA(n){
this.name = n
}
classA.prototype.getName = function(){
return this.name
}
var x = new classA('john')
console.log(x.getName())
My question is: can I group multiple methods inside a namespace? So I would like to do that:
var x = new classA('john')
console.log(x.CONSTANT.getName())
So I would like to call some methods as x.someMethod() and others as x.CONSTANT.otherMethod()
PS: I'm looking for a cross-browser method. Bind is not working in Safari and IE9.
You can do it, for example, via bind. Google es5 shim for implementation of bind in browsers, which don't support it natively.
function MyClass(name) {
this.name = name;
this.CONSTANT.otherMethod = this.CONSTANT.otherMethod.bind(this);
}
MyClass.prototype.CONSTANT = {
otherMethod: function() {
alert(this.name);
}
};
As far as I know a constant is just a property and it can't contain methods, you need to separate your objects and use methods to have the same effect:
function A (id) {
this.id = id;
this.showId = function () { return this.id; }
};
function B (a) {
this.a = a;
this.getA = function () { return this.a; }
}
var a = new A(12);
var b = new B(a);
b.getA().showId();
edit:
You can use a literal object as follow
function B (id) {
this.id = id;
this.CONSTANT = { otherMethod: function () { alert("..."); } };
someMethod = function () { return this.id; }
}
but the literal CONSTANT object can't access B-object methods,
Consider the #kirilloid post to round this.
You can, but you have to be careful because it won't act like you think it will. The this for the method will be the namespace, not the root object.
For example, in x.CONSTANT.getName(), the this object will be x.CONSTANT, and not x.
Here's some sample code which kinda does what you ask (or in jsfiddle):
function MyClass() {}
MyClass.prototype.CONSTANT = {
getName: function() {
alert('Foo');
}
};
var c = new MyClass();
c.CONSTANT.getName();
To make sure the this is right, you need to do much more.
You can use getters/setters (read this article) to achieve this. For example you may define it like this:
classA.prototype.__defineGetter__('CONSTANT', function() {
var that = this;
return {
getName: function() {
return that.name;
}
};
});
Note that holding reference to the object. It will work now
x = new classA('test');
x.CONSTANT.getName();
// result - test
I'm looking for the most optimized way to have an object in JS; since JS allows you to do something in multiple ways I want to know which is considered to be "best practice".
A conceptual use of the object would be this:
var John = new Person('John');
var Foo = new Person('Foo');
console.log(John.getName()); //Return 'John'
console.log(Foo.getName()); //Return 'Foo'
console.log(John.name); //undefined
console.log(Foo.name); //undefined
I have some examples here:
Example #1:
var Person = function (name) {
this.getName = function () { return name; }
}
Here I actually have no properties; "name" cannot be changed or be read by public and getName method can be accessed public and invoke with local name variable. This actually meets my needs.
Example #2:
function Person (name) {
this.getName = function () { return name; }
}
This has same behaviour as example #1. I'm just not sure about the difference between var method = function () {}; and function method() {}; from a functional and performance perspective.
Example #3:
var Person = function (name) {
this.name = name;
Person.prototype.getName = function () { return this.name; }
}
Here I have name property which can be read/write by public and I also have a prototype getName method that can be accessed public.
Example #4:
var Person = function (name) {
this.name = name;
if (!Person._prototyped) {
Person.prototype.getName = function () { return this.name; }
Person._prototyped = true;
}
}
Here I have what I had in example #3 with the difference that I make sure that prototype methods are set only once and only when required.
So the end question is, which of those you will suggest me to follow or if any of them then which way is the best practice?
For what you want, the best way is probably this:
/**
* #constructor
*/
function Person(name) {
this.getName = function() {
return name;
};
}
Why is this? Well, first of all, encapsulation. If possible, you generally want to put the function in the prototype, like so:
/**
* #constructor
*/
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
};
However! In this case, it appears you don't want Person.name to be accessible. For that reason, you need to use closures.
As for this method:
var Person = function (name) {
this.name = name;
Person.prototype.getName = function () { return this.name; }
}
That's not good. You publicly expose this.name, so it offers no advantage over the previous prototype method, but you continually overwrite Person.prototype.getName with the same function. There's no point in doing that; this will be the appropriate object every time. What's more, Person.prototype.getName won't be accessible until the first Person object is instantiated so there's not much point in making it "public" in the first place. Your fourth example is basically identical, with more cruft making it harder to understand, but it still has all the disadvantages.
So, in this case, go with the first version; when possible, though, set methods on prototype so they can be called outside of an instance.
Finally, I would recommend using:
function Person() {
}
over
var Person = function() {
}
because 1) The second example is missing a semicolon, 2) the var implies that the constructor is variable which it should not be, and 3) I don't believe JDoc allows #constructor to be applied to it, causing a warning in Closure Compiler at least1.
1 Okay, not so important. But still...
In example 3 and 4 it should be:
var Person = function (name) {
this.name = name;
};
Person.prototype.getName = function () { return this.name; }
And:
var Person = function (name) {
this.name = name;
};
if (!Person._prototyped) {
Person.prototype.getName = function () { return this.name; }
Person._prototyped = true;
}
As you don't need to mess with the prototype each time you call the constructor.
Not sure which is fastest (as they are all valid for your purposes), which is what your asking, but I wouldn't worry as this seems like micro-optimizing. If you must know then you can use a site like http://jsperf.com/
The fastest way I can imagine would be :
function Person(name) {
this.getName = function() {
return name;
};
}
As minitech said. The reason is as follows:
Each time the js engine has to go "up" the prototype chain it takes away a fraction of a ms (or fraction of a sec on IE :) ), and as declaring variables can take up time (also negligible) you avoid doing that too. Hope that helps
Works well on node.js. AFAIK, arguments are mutable. Closures will remember values. Hence this will work. I guess this solves it all.
var Person = function(Name) {
this.getName = function(){return Name;}
this.setName = function(newName) { Name = newName; }
},
me = new Person('John');
console.log(me.getName());
me.setName('Peter');
console.log(me.getName());