This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 4 years ago.
When defining javascript objects that behave like classes that have state and functions that manipulate that state is it better to define functions when defining the object like so:
function MyNewClass(){
//State
this.value = ""
this.otherValue = ""
//Functions
this.someFunction = function(){
//Some logic here
}
}
Or it it better practice to define functions on the prototype of the object such as:
function MyNewClass (){
//state
this.value = ""
this.otherValue = ""
}
MyNewClass.prototype.someFunction = function(){
//Some logic here
}
Are there any advantages to defining object functions on the prototype?
Thanks!
Because functions are objects, given the described scenario, we have two behavior:
If you declare the function on the "class" function, every object you
create then it will have a copy of that function (object), so the
memory usage will increase.
However, if you add the function to the prototype, the function will
be shared by all the objects, so there will be a save of memory
You can see the difference for yourself by running this code:
var output = function(s) { document.getElementById("output").innerText += s; }
function MyNewClass() {
this.foo = function() {
output("1");
}
}
MyNewClass.prototype.bar = function(){
output("2");
};
var a = new MyNewClass();
a.foo();
a.bar();
a.foo = function() { output("3") };
MyNewClass.prototype.bar = function() { output("4"); };
a.foo();
a.bar();
var b = new MyNewClass();
b.foo();
b.bar();
The output is: 123414
When you change a function as a member variable, you only change that instance. If you change it in the prototype, it affects all instances.
functions of the object should be declared using prototype because prototype is a common space that is shared by all the objects created by the same constructor function and it also saves memory because all objects do not have there own functions created but they all are pointing to one common place.
you can refer it here
https://www.youtube.com/watch?v=fBpPfPjxOhc&list=PLqq-6Pq4lTTaflXUL0v3TSm86nodn0c_u
example
enter code here
//constructor function
function gh(){
this.x=1;
}
//now if you create a object
var p=new gh();
//now i need function show in my object p
function show(){
console.log(x);
}
gh.prototype.show=show();
//it will be added all objects automatically (to understand this study scope chain)
Related
While reading other people's source code and various articles over the web, I found that when different people use "object-oriented-style" programming in JavaScript, they often do it quite differently.
Suppose, I want to create a tiny module having 1 property and 1 function. I've seen at least 4 approaches to this task:
// Option 1
var myObject1 = {
myProp: 1,
myFunc: function () { alert("myProp has value " + this.myProp); }
};
// Option 2
var myObject2 = function () {
return {
myProp: 1,
myFunc: function () { alert("myProp has value " + this.myProp); }
};
}();
// Option 3
var MyObject3 = function () {
this.myProp = 1;
this.myFunc = function () { alert("myProp has value " + this.myProp); }
};
var myObject3 = new MyObject3();
// Option 4
var MyObject4 = function () { };
MyObject4.prototype.myProp = 1;
MyObject4.prototype.myFunc = function () { alert("myProp has value " + this.myProp); };
var myObject4 = new MyObject4();
All these approaches are syntactically different but seem to produce objects that can be used in the same way.
What's the semantic difference between them? Are there cases when for some reason I should choose one of these options over all the rest?
myObject1 is an object literal (singleton). Useful in cases where you want to have just one object of this type. Look at it as a static object.
myObject2 returns an object literal. So right after doing var foo = myObject2(), the variable foo will hold the result { myProp: 1, myFunc: function(){...} } with reference to the parent function that has executed. This is called a closure. This can be used to define a public API or modules, for example.
i.e.:
var foo = (function(){
var privateProp = "I am a private property";
// the object below is returned, privateProp is accessible
// only through foo.publicProp
return {
publicProp: privateProp
}
})();
The privateProp property is now accessible through foo.publicProp.
MyObject3 and MyObject4 are constructor functions. By using the new keyword before the function call, you tell JavaScript to create an instance of that object. This means that every new object created this way will inherit properties and methods from the object definition.
The difference between MyObject3 and MyObject4 is that in the case of the former, every instance of that object will have its own copy of the myProp and myFunc properties, whereas the latter will only reference those properties. That means that no matter how many instances of object MyObject4 you create, there will be only one of myProp and myFunc.
I recommend you look up on how closures, prototypal inheritance, and several object design patterns (modules, etc.) work in JavaScript.
Both 1. and 2. are pretty much identical in your example. You could make 2. make an actual difference by declaring "private" variables in the IIFE's scope, like this:
var myObject2 = function () {
var myPrivateProp = ...;
return {
getPrivateProp: function() { return myPrivateProp; }
};
}();
In general, those create a value, not something that you would call a class of values.
Instead, what 3. and 4. are doing is creating a prototype that can be then used to create more usable values out of it. Whether you actually declare the defaults on the prototype or in the constructor doesn't make much difference.
So, to sum up, 1&2 are something like a "lambda" object, without a named prototype, while 3&4 actually make the thing reusable and recreatable.
This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 9 years ago.
I am wondering if there are any advantages of using any of these over the other, and which way should I go?
Constructor approach:
var Class = function () {
this.calc = function (a, b) {
return a + b;
};
};
Prototype approach:
var Class = function () {};
Class.prototype.calc = function (a, b) {
return a + b;
};
I don't like that, using the prototype, method definitions are separated from the class, and I'm not aware if there is any specific reason I should use this over just the first approach.
Also, is there any benefit of using a function literal to define a "class", over just function definition:
var Class = function () {};
vs
function Class () {};
Thanks!
Methods that inherit via the prototype chain can be changed universally for all instances, for example:
function Class () {}
Class.prototype.calc = function (a, b) {
return a + b;
}
// Create 2 instances:
var ins1 = new Class(),
ins2 = new Class();
// Test the calc method:
console.log(ins1.calc(1,1), ins2.calc(1,1));
// -> 2, 2
// Change the prototype method
Class.prototype.calc = function () {
var args = Array.prototype.slice.apply(arguments),
res = 0, c;
while (c = args.shift())
res += c;
return res;
}
// Test the calc method:
console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));
// -> 3, 3
Notice how changing the method applied to both instances? This is because ins1 and ins2 share the same calc() function. In order to do this with public methods created during construction, you'd have to assign the new method to each instance that has been created, which is an awkward task. This is because ins1 and ins2 would have their own, individually created calc() functions.
Another side effect of creating methods inside the constructor is poorer performance. Each method has to be created every time the constructor function runs. Methods on the prototype chain are created once and then "inherited" by each instance. On the flip side of the coin, public methods have access to "private" variables, which isn't possible with inherited methods.
As for your function Class() {} vs var Class = function () {} question, the former is "hoisted" to the top of the current scope before execution. For the latter, the variable declaration is hoisted, but not the assignment. For example:
// Error, fn is called before the function is assigned!
fn();
var fn = function () { alert("test!"); }
// Works as expected: the fn2 declaration is hoisted above the call
fn2();
function fn2() { alert("test!"); }
The advantage of the prototype approach is efficiency. There is one calc() function object shared between all Class objects (by which I mean objects created by calling the Class constructor). The other way (assigning methods within the constructor) creates a new function object for every Class object, using more memory and taking more processing time when calling the Class constructor. However, this approach does have an advantage: the calc() method has access to local variables within the constructor, which you can use to your advantage:
function Class() {
var calcCallCount = 0;
this.calc = function (a, b) {
++calcCallCount;
alert("Calc called " + calcCallCount + " times");
return a + b;
};
};
Regarding var Class = function() {...} versus function Class() {...}, I generally prefer the latter is because it means the function has a name, which can be useful when debugging. The other difference is that the latter version (a function declaration) is hoisted, meaning that it is available everywhere within the scope in which it is defined, not just after the definition. However, some people prefer to use the former (a function expression) everywhere.
var YourClass = function(){
var privateField = "somevalue";
this.publicField = "somevalue";
this.instanceMethod1 = function(){
//you may access both private and public field from here:
//in order to access public field, you must use "this":
alert(privateField + "; " + this.publicField);
};
}
YourClass.prototype.instanceMethod2 = function(){
//you may access only public field 2 from this method, but not private fields:
alert(this.publicField);
//error: drawaback of prototype methods:
alert(privateField);
};
Advantages of prototype methods:
When you define methods via prototype, they are shared among all YourClass instances. As a result the total size of such instances is < than if you define methods in constructor; There are tests that show how method definition via prototype decrease the total size of html page and as a result a speed of its loading.
another advantage of methods, defined via prototype - is when you use inherited classes, you may override such methods and in the overriden method of the derived class you may invoke the method of base class with the same name, but with methods defined in constructor, you cannot do this.
This question already has answers here:
How does "this" keyword work within a function?
(7 answers)
Closed 8 years ago.
I have a function in JavaScript:
function main() {
console.log(this);
}
How come this logs Document? Surely it should log function main?
If not, then how do I declare a variable within main to be accessed by the rest of the code as main.varName?
Thank you!
Hey you can do something like this.
But then this would look something like a class object.
<script>
function main() {
this.testVar = "124";
}
var testMain = new main();
alert(testMain.testVar);
</script>
The alternative is that you just create a normal global variable.
The way i am taking the code is a more class object way.
Hope i could help :)
The this keyword references the context of the function, not the function itself.
When you call a function as a method of an object, then this references the object, otherwise the context is the global context (document).
Example:
var o = {
name: 'myObject',
fn: function(){ alert(this.name); }
};
o.fn(); // alerts "myObject"
As a function is also an object, you can add properties to it:
function main() {
}
main.varName = 42;
alert(main.varName); // shows "42"
However, this is not a regular use of functions and objects. Normally main would be a plain object rather than a function if you want to access main.varName.
Also, check out the module pattern
var person = function(){
return module = {
setName: function(name){
module.name=name;
}
}
};
var bill = person();
bill.setName('bill');
console.log(bill.name);
This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 9 years ago.
So, I am not a JavaScript expert, just trying to understand what the difference is between two following snippets of code. I have a project that I want to convert to TypeScript and I need to understand the difference between two code snippets being generated.
var Pony = (function () {
function Pony() { }
Pony.prototype.bite = function () {
alert("Chomp!");
};
return Pony;
})();
var Pony2 = (function () {
function Pony2() {
var self = this;
self.bite = function () {
alert("Chomp!");
};
}
return Pony2;
})();
The difference between the two is that you can get to the prototype of the first Pony via attributes on the object stored in var Pony and could expand upon or use the associated bits of that prototype elsewhere where as Pony2 would just be considered a function. So if you do not plan on using any sort of prototypical inheritance later on they are equivalent.
The answers above give a good overview on the difference between putting on the prototype and putting on the instance. As to your question about converting to TypeScript, below is how you would write them both:
class Pony {
bite(){
alert('chomp');
}
}
class Pony2 {
bite: () => void;
constructor(){
this.bite = () => alert('chomp');
}
}
As far as how you use them, there's no difference. However, from a performance standpoint the former method would be preferable. Let's extend your example a little bit:
var prototypePony1 = new Pony();
var prototypePony2 = new Pony();
var thisPony1 = new Pony2();
var thisPony2 = new Pony2();
prototypePony1.hasOwnProperty('bite'); //returns false
prototypePony2.hasOwnProperty('bite'); //returns false
thisPony1.hasOwnProperty('bite'); //returns true
thisPony2.hasOwnProperty('bite'); //returns true
Pony.prototype.bite = function() { alert('Nomnomnom!'); };
Pony2.prototype.bite = function() { alert('Nomnomnom!'); };
prototypePony1.bite(); //alerts 'Nomnomnom!'
prototypePony2.bite(); //alerts 'Nomnomnom!'
thisPony1.bite(); //alerts 'Chomp!', instance property is accessed first
delete thisPony2.bite;
thisPony2.hasOwnProperty('bite'); //returns false
thisPony2.bite(); //alerts 'Nomnomnom!'
In the example above, thisPony1 and thisPony2 both get their own copy of the bite function, since it was defined using this However, prototypePony1 and prototypePony2 both share the same copy of bite from Pony's constructor.
Once we define the bite prototype on Pony2, the instance property is still accessed first on thisPony1. It's not until we delete the instance property that we see the newly defined prototype property on thisPony2.
For more detailed info on defining object methods, have a look here.
This question already has answers here:
this.constructor.prototype -- can't wholly overwrite, but can write individual props?
(2 answers)
Closed 6 years ago.
If I declare the base prototype object outside the constructor for an object, all created objects are based on that single base object which is not suitable for my needs because I need more than one instance of the base object.
In short: Is this code correct? It works but I'm picky about having correct code.
Example:
function BaseObject()
{
BaseObject.prototype.insertObject = function()…
…
… // Some other functions.
}
function Object1()
{
Object1.prototype = new BaseObject();
Object1.prototype.coolFunction = function()…
…
… // Same kind of pattern.
}
function Object2()
{
Object2.prototype = new Object1();
Object2.prototype.incredibleFunction = function()…
…
… // You get the idea.
}
The general pattern:
function Base ( baseMember ) {
this.baseMember = baseMember;
}
Base.prototype.baseFunc = function () {};
function Derived ( baseMember, derivedMember ) {
Base.apply( this, arguments );
this.derivedMember = derivedMember;
}
Derived.prototype = Object.create( Base.prototype );
Derived.prototype.constructor = Derived;
Derived.prototype.derivedFunc = function () {};
It's ugly, I know...
No, all the code that is currently inside your constructor functions should be outside of them. Right now you are reassigning those properties of the prototype every time someone creates a new object.
Finally, points of good-practice:
You should always "fix" the constructor property of any derived prototypes. This is a quirk of JS inheritance; it gets overwritten. People rarely depend on the constructor property being correct, but sometimes they do, and it just feels wrong if you don't.
Object.create(Base.prototype) is better than new Base() if you are working in browsers that support it, or using es5-shim. It only instantiates the object, instead of creating it, which is good since you don't need an actual copy of the object to perform prototypal inheritance.
This would all look like:
function BaseObject() { }
BaseObject.prototype.insertObject = function () { };
function Object1() { }
Object1.prototype = Object.create(BaseObject.prototype);
Object1.prototype.constructor = Object1;
Object1.prototype.coolFunction = function () { };
function Object2() { }
Object2.prototype = Object.create(Object1.prototype);
Object2.prototype.constructor = Object2;
Object2.prototype.incredibleFunction = function () { };