Question about create object in JavaScript - javascript

I've learned that you can create your own 'class' in this way:
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.foo = function(){
// do something
}
Person.prototype.foo2 = function(){
// do something
}
var wong2 = new Person("wong2", "20");
Now if foo and foo2 both need to call another function named foo3, where should I add it to?
I don't want foo3 to be called by wong2, so I can't just use
Person.prototype.foo3 = function(){
// something else else
}
But if I define it in the global scope, I don't think it's very nice. Any suggestions?

You can define foo3 inside a closure that foo1 and foo2 have access to, something like
function() {
function foo3() { ... }
Person.prototype.foo = function(){
foo3();
}
...
}();

Try to look at this SO question and article about Private Members in JavaScript.

Don't know if this is exactly what you are looking for, but this acts as a static function.
Person.foo3 = function() {
// something else else else but not inherited by wong2
}

why not create your own namespace? try
var person = {};
person.createPerson=function (name,age){
this.name=name;
this.age=age;
if (age<18){
this.status = 'cannot Marry';
}else{
person.addMarriageStatus('married');
}
}
person.addMarriageStatus = function(status){this.status=status};
person.createPerson('Jack',2);
//person

I get the impression you want something like a static function, where foo3 belongs to Person, but not to wong2 and certainly not to the global scope.
If so, just assign a function to Person.foo3 as i have below.
http://jsfiddle.net/audLd/1/
function Person(name, age){
this.name = name;
this.age = age;
}
Person.foo3 = function() {return 10;};
Person.prototype.foo = function(){
return Person.foo3();
}
Person.prototype.foo2 = function(){
return Person.foo3()*2;
}
var wong2 = new Person("wong2", "20");
alert("" + wong2.foo() + ", " + wong2.foo2()); //works
alert("" + Person.foo3()); //works. this is the distinction between what I'm loosely calling static and private
alert(foo3()); //doesnt work
alert(wong2.foo3()); //doesnt work
If you want a 'private' member thru closures then that is an entirely different animal.

Related

How to use object oriented without using keyword ('new')

What am I trying to do is as following:
var Person = function(name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
}
// This will return error;
console.log(Person('John').getName());
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
Am I misunderstanding something?
// This will return error;
console.log(Person('John').getName());
it returns an error bcoz Person() by default returns undefined ,but if you use new it will return the newly created object.
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
this works bcoz a new object with __proto__ set to Person.prototype is returned and since there is a getName() on it , it works as expected.
you may use scope safe constructor for your constructor to work without explicit new.
function Person(name) {
if(this instanceof Person) {
this.name = name;
} else {
return new Person(name);
}
}
http://www.mikepackdev.com/blog_posts/9-new-scope-safe-constructors-in-oo-javascript
If you don't want to have the new keyword all over your code (and I can't think of a good reason to want that, you would be basically hiding an important information), you could just do something like:
var pPerson = function(name) {
this.name = name;
};
pPerson.prototype.getName = function () {
return this.name;
};
var Person = function (name) {
return new pPerson(name);
};
You can use Object.create() if you don't want to use the new keyword. Here's an example from MDN:
// Animal properties and method encapsulation
var Animal = {
type: "Invertebrates", // Default value of properties
displayType : function(){ // Method which will display type of Animal
console.log(this.type);
}
}
// Create new animal type called animal1
var animal1 = Object.create(Animal);
animal1.displayType(); // Output:Invertebrates
// Create new animal type called Fishes
var fish = Object.create(Animal);
fish.type = "Fishes";
fish.displayType(); // Output:Fishes
If you really really hate your self, you can do this
var Person = function(name) {
var This = {};
This.name = name;
//See note
Object.setPrototypeOf(This, arguments.callee.prototype);
return This;
}
Person.prototype.getName = function () {
return this.name;
}
var p = Person('John');
console.log(p.getName());
Note
You absolutely have to read about this.
You can try creating prototype functions as a part of parent function itself.
var Person = function(name) {
this.name = name;
this.get_name = function() {
return this.name;
}
return this;
}
Person.prototype.getName = function() {
return this.name;
}
// This will return error;
console.log(Person('John').get_name());
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());

Is it possible to access the prototype variable GLOBALLY

function Person() {}
Person.prototype.getFullName = function(){
var name = "John Micheal";
}
var p1 = new Person();
console.log(p1.getFullName());
Here I want to access the variable "name" to my other prototypes. Is this possible?
If not, Is there any other way to do ?
http://jsfiddle.net/KabeerRifaye/bcxqx1wj/
Thanks in advance.
You should probably go do some JavaScript tutorials. I recommend TreeHouse or CodeSchool.
Anyways, there are a few possible options / interpretations of your question.
If you're just trying to get the return value you need to use the return keyword. Now your console.log will output the name.
function Person() {}
Person.prototype.getFullName = function(){
var name = "John Micheal";
return name;
}
var p1 = new Person();
console.log(p1.getFullName());
If you truly want to share the value between functions you need to use the this keyword. In this example you can set the value in setName and retrieve it with getName.
function Person() {}
Person.prototype.getName = function(){
return this.name
}
Person.prototype.setName = function(newName) {
this.name = newName
}
var p1 = new Person();
p1.setName('John');
console.log(p1.getName());
These are hard concepts to learn on your own. I really recommend working through some JavaScript tutorials to learn this fundamental concepts.
I updated your version => http://jsfiddle.net/bcxqx1wj/3/
I would highly recommend to use a more generic get function:
Person.prototype.getData = function(prop){
if (this[prop] !== undefined) {
return this[prop];
} else {
return false;
}
}
Set function would look like this:
Person.prototype.setData = function(prop, data){
this[prop] = data;
}

What am I doing wrong with this prototype setup?

See the simplified code. What am I not getting with this pattern?
var john = new person('john');
john.hi();
function person(name) {
this.name = name;
}
person.prototype.hi = function() {
console.log('hi there. Name is ' + this.name);
};
If there's anything wrong it is the order of things. Other than that this seems correct.
function person(name) {
this.name = name;
}
person.prototype.hi = function() {
console.log('hi there. Name is ' + this.name);
};
var john = new person('john');
john.hi();
You could also add prototype function after the creation of your object, and this function can be called by all the instances, even those created before. Because when you call a function, the prototype chain will be searched if no function is found on your object itself.

Solving ugly syntax for getter in js

Let's take this object:
var person = {
_name: "John",
name: function() {return _name}
}
In GUI,
myTextBox.value = person.name()
will return
"John"
But
myTextBox.value = person.name
will return
function() {return _name}
How can I force both syntax to return "John"? Could I use a closure (question I asked previously) somehow here?
You can't!
You can't override javascript operators or keywords.
you really can't have one operator\keyword that does two different things in the same context!
Ok, had a play and it looks like this is "possible" (At least in chrome) but its a bit of a dirty hack.
var person = {
_name: "John",
name: function() {return this._name;},
}
person.name.toString = function(){ return person._name; }
Which will result in both person.name and person.name() returning "John".
If you support only modern browsers you can use a ES5 Getters, but in general this is JavaScript, why are you trying to make it complicated?
Your alternatives are:
make a rule that you have to use the function to access the variable (yuck)
don't worry about it.
I'd go for #2.
I think you're getting confused with this syntax here, but actually it has the same problem as you do now:
function Person(name) {
this._name = name;
}
Person.prototype.name = function(name) {
if (name) this._name = name;
return this._name;
}
var j = new Person("Jay");
j.name() // "Jay"
j.name("Thomas"); // I can set the value as well
j.name() // "Thomas"
It seems like you're trying to create real private variables, which are possible, but probably not that helpful.
function Person(name) {
var myName = name; // private
this.name = function() {
return myName;
}
}
var j = new Person("Jay");
j.name(); // still had to use perens
Finally because yours is just a simple object, we can do this. Not sure why you'd want to though:
var person = {};
(function(name) {
var myName = name; // myName and name, both private, but not helpful
person = {
name = myName
}
}("Jay"))
person.name // "Jay"

Most optimized way to create JS Object

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());

Categories