I am trying to learn more about JavaScript OO Programming, but am seeing conflicting methods to create a "Class"-like object. I am wondering if there are any substantial differences in these two methods:
Method 1
function Person(name){
this.name = name;
this.setName = function(val){
this.name = val;
}
this.getName = function(){
return this.name
}
}
var John = new Person("John");
Method 2
function Person(name){
var exports = {};
exports.name = name;
exports.setName = function(val){
this.name = val;
}
exports.getName = function(){
return this.name
}
return exports;
}
var Bob = Person("Bob");
I have seen these two methods used for creating a complex JavsScript object. I have even seen large JS plugins like jQuery use method 2 instead of method 1 to set up their jQuery functions. Is one of these faster or more efficient than the other in any way?
The first one creates an object of the type Person, while the second one creates an object of the type Object. The first one allows you to add members to the prototype of Person.
You can put all the functions in the prototype instead of creating new functions for every instance:
function Person(name){
this.name = name;
}
Person.prototype = {
setName: function(val){
this.name = val;
},
getName: function(){
return this.name
}
}
Related
I'm trying to learn JavaScript, but got stuck with a problem (more with misunderstanding "this" keyword) that doesn't give me move on.
I've watched a lot of content about it and barely understood it, but still have some troubles.
I have some code:
function Person (name, age) {
this.name = name;
this.age = age;
this.changeName = function (name) {
this.name = name;
}
}
What do we use "this" here for?
As I understood we use "this" to create variable inside function constructor and give it value of our "name" parameter that we could refer to it. Am I right?
Then I have this code:
var p1 = new Person ("John", 30);
p1.changeName ("Jane");
console.log(p1.name);
As I sorted out here, we call method that overwrites our variable that we created to refer to. But it doesn't change actual parameter. So if it's right why do we use it? Doesn't it matter to have actual "name" parameter changed?
The whole code is from teaching app!
So if it's right why do we use it? Doesn't it matter to have actual "name" parameter changed?
No, there's no need to do that in this example. changeName changes the property on the object that was created by new Person.
It's true that that example code is a bit odd, because it creates the changeName function in the constructor but doesn't do the kinds of things you'd normally do when you create the function in the constructor. I'd expect that code to either be this, which puts the changeName on the prototype:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.changeName = function(name) {
this.name = name;
};
(or the class equivalent) or this:
function Person(name, age) {
this.getName = function() {
return name;
};
this.changeName = function(newName) {
name = newName;
};
this.getAge = function() {
return age;
};
}
That code does update the parameter (which has no effect at all on the code calling Person). It doesn't create name and age properties at all; instead, it just makes their values accessible via getName and getAge. There's also a function to change name (changeName); but there's no function to change age. People write code like that so that age cannot be changed from outside code created within the Person constructor.
I guess you may misunderstand which parameter you actually change, so I rewrite it like so, holp this helps.
function Person (argument_name, argument_age) {
this.name = argument_name;
this.age = argument_age;
this.changeName = function (argument_change_name) {
this.name = argument_change_name;
}
}
let p1 = new Person ("John", 30);
p1.changeName ("Jane");
console.log(p1);
The this keyword is used to create and assign values to variables in the class. It is again used to create functions, either getters or setters. So in your code this.changeName is a function that when passed a value will change the name of the person.
eg.
var a = 5; // a is an integer
var b = "Han"; //b is a string
var c = function(name){
//code here
} // then c is also a function;
For example, we have a function
function FirstFunction(name, surname){
this.name = name;
this.surname = surname;
...
}
We have some functions in its prototype and we have another function "SecondFunction" with it's own prototype. When I want to inherit prototypes I write
SecondFunction.prototype = Object.create(FirstFunction.prototype);
Now, when I try to create new variable with
var newVariable = new SecondFunction();
I want to pass arguments 'name' and 'surname' that are listed in the FirstFunction to be able to use functions in the FirstFunction's prototype. Which is the best way to do that?
I think the right way to do it is using call or apply :
function FirstFunction(name, surname){
this.name = name;
this.surname = surname;
}
function SecondFunction(name, surname) {
FirstFunction.call(this, name, surname)
}
SecondFunction.prototype = Object.create(FirstFunction.prototype);
var newVariable = new SecondFunction('Harry', 'Potter');
console.log(newVariable);
You can refer to this article that explains it.
I had written this code to simulate OOP inheritance and calling baseclass in javascript and it works:
function Animal(name,age)
{
this._name = name;
this.setName = function (name) { this._name = name }
this.getName = function() { return this._name }
}
function Cat(name,age)
{
Animal.call(this,name,age); // call baseclass constructor
this.getName = function() { return Cat.prototype.getName.call(this)+", a cat" }
}
Cat.prototype = new Animal(); // will create the baseclass structure
/// ***** actual execution *****
var puss = new Cat("Puss",3);
var cheshire = new Cat("Cheshire",10);
// do some actions
console.log ( puss.getName() );
// change cat's name
puss.setName("Puss in boots");
alert ( "new name -->"+puss.getName() );
problem is that, for each instance of "new Cat()" the "getName" and "setName" functions are replicated.
I have read a lot of articles on prototyping but none addressed the issue of calling the baseclass function.
You should assign the methods to the prototype of the function, for example,
function Animal(name, age) {
this._name = name;
this._age = age;
}
Animal.prototype.getName = function () { return this._name; }
Animal.prototype.setName = function (value) { this._name = value; }
function Cat(name, age) {
Animal.call(this, name, age);
}
Cat.prototype = new Animal();
Cat.prototype.getName = function () {
return Animal.prototype.getName.call(this) + ", a cat";
}
Are you looking for __proto__ which stores prototype data?
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/Proto
If you do a console.log(puss.__proto__.getName) you'll get what seems to be the "baseclass" function but I'm not sure how cross-browser is this.
From http://phrogz.net/js/classes/OOPinJS2.html
Javascript does not have any sort of 'super' property, which would
point to its parent class. Instead, you use the call() method of a
Function object, which allows you to run a function using a different
object as context for it. If you needed to pass parameters to this
function, they would go after the 'this'.
In your case it works the same for functions as "methods", so you can do:
Animal.prototype.setName.call(this, name);
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());
I have an object written like this:
Object1.prototype = {
isInit: false,
Get : function (){}
}
Now I'd like to add a constructor which takes one parameter. How can I do it?
Class declaration
var User = function(name, age) { // constructor
}
User.prototype = {}
Instance variables (members)
var User = function(name, age) {
this.name = name;
this.age = age;
}
User.prototype = {}
Static variables
var User = function(name, age) {
this.name = name;
this.age = age;
}
User.prototype = {
staticVar: 15,
anotherStaticVar: 'text'
}
Here I defined two static variables. Each User instance has access to these two variables. Note, that we can initialize it with value;
Instance functions (methods)
var User = function(name, age) {
this.name = name;
this.age = age;
}
User.prototype = {
getName: function() {
return this.name;
},
setName: function(name) {
this.name = name;
}
}
Usage example:
var user = new User('Mike', 29);
user.setName('John');
alert(user.getName()); //should be 'John'
Static functions
var User = function(name, age) {
this.name = name;
this.age = age;
}
User.create = function(name, age) {
return new User(name, age);
}
User.prototype = {}
Assuming that by "ctor" you mean "constructor", in JavaScript that's just a function. In this case your constructor would need to be "Object1" itself - in other words, what you've got there makes sense if you have already defined "Object1" to be a function.
Thus,
function Object1(param) {
// constructor code
}
would be the constructor for your type.
Now there are some JavaScript libraries that provide a utility layer for defining classes. With those, you generally pass some sort of object (like you've got) that includes an "init" function. The libraries provide APIs for creating "classes" and for extending one class from another.
Javascript has prototype based object model. Check this mozilla wiki page and suddenly you'll feel much better in js land.
We can define a constructor in javaScript is same as we fine function, so constructor is just a function.
//function declaration
function func(){}
In case of Contructor We use initial letter in caps in construct like
//constructor
function Func(){}
now do whatever you want to with your constructor
var constructor1 = new Func();
class CLASS_NAME
{
private:
int variable;
public:
CLASS_NAME() //constructor
{
variable = 0;
}
};