I want to implement java script Singleton in my script.
Some of the variables of the Singleton have the same values for all users, but others will very from user to user.
I want to understand better - is Singleton create one instance for all the session running or every session will manage her own object.
One of the variables will be logger/counter - will all the users/sessions share its value?
My object will look something like this:
var VideoLog = (function () {
/** logger vars **/
this.logger = 0;
this.somevar = null;
this.somefunction = function () {
come code..
}
})();
The Singleton pattern is designed specifically to limit the number of instances of an object to one. This pattern is good for system-wide scripts.
I would suggest using the Constructor pattern. This way you can create a parent object that defines shared fields across objects. Then, create other objects from the parent which can have their own unique fields.
function Cat( breed, age ) {
this.breed = breed;
this.age = age;
}
var tabby = new Cat( "tibs", 3 );
var blue = new Cat( "Thomas", 6 );
tabby.color = 'orange';
blue.color = 'grey';
Related
I am writing domain objects in Javascript which gets populated with the database fields. Suppose I have two objects dog and cat and I have following constructor function definition:
function Dog(opt_data) {
var data = opt_data || {};
this.createdAt = data['created_at'];
this.updatedAt = data['updated_at'];
this.name = data['name'];
this.breed = data['breed'];
}
function Cat(opt_data) {
var data = opt_data || {};
this.createdAt = data['created_at'];
this.updatedAt = data['updated_at'];
this.name = data['name'];
this.fur = data['fur'];
}
Now, both of the above objects have craetedAt and updatedAt properties. So, should I create a new class BaseModel which has there properties and let all the objects inherit that or is there any better alternative in javascript for this pattern?
Update 1:
My understanding from comments and answer.
function Cat(opt_data) {
var data = opt_data || {};
this.name = data['name'];
this.fur = data['fur'];
this.updateTimestamp(data);
}
Cat.prototype = Object.create({
updateTimestamp: function(data) {
this.createdAt = data['created_at'] || new Date();
this.updatedAt = data['updated_at'] || new Date();
}
});
Unless the createdAt and updatedAt values have some common supporting methods or accessors that you need to define on both Dog and Cat objects, just set the attributes to whatever value you need them to be.
Since you don't declare object members in JavaScript (the way you would in C++, C#, Java, etc.), there's nothing to be gained by inheriting from a BaseModel prototype in the case you have proposed. That is to say, since you don't have to do anything in JavaScript to create the createdAt and updatedAt attributes other than to simply assign to them, a base type does not really provide anything useful because you would just have to assign those attributes in the base type constructor anyway.
Where you may need a base type is if both objects need to have similar methods to save and load data (presumably automatically updating the updatedAt attribute when saving). In this case, giving both Dog and Cat a prototype with save and load methods would be a useful application of the prototypical inheritance pattern.
Im reading this article from Crockford:
http://www.crockford.com/javascript/private.html
And in the section where he talks about Private, he says:
Private members are made by the constructor. Ordinary vars and parameters of the constructor becomes the private members.
Now if I do this in my script:
"use strict"
function car(brand) {
this.brand = brand;
var year = 2012;
var color = "Red";
}
var bmw = new car("BMW");
console.log(bmw.brand); // BMW -> VISIBLE ?!?
I can easily access property that was passed through constructor!
Can someone explain this better, shouldn't these variables passed through constructor be private?
Thanks!
I think you've mis-interpreted that bit of information. It doesnt say that private methods are those that are "passed through" the constructor, it says its those that are "made by" the constructor.
To be clear, look at this:
function car(brand) {
var year = 2012;
var color = "Red";
}
That has 3 private variables. brand,year and color. By adding this line
this.brand = brand
You are creating a public property and assigning it the value from your private variable. That you've named the public property and the private variable the same thing is neither here nor there, if it makes it clearer think of it as
this.publicBrand = brand
It's not that you can access values passed into the constructor. What you've done is set this.brand equal to the value passed in the constructor. Therefore, the publicly available brand now has the same value that was passed in. The local brand inside the constructor != this.brand until you set it.
Everything you assign to the context (this inside function) is public available. Be aware that the context is the window object if you call the function without new
"use strict"
function car(brand) {
this.brand = brand; //Public (can be accessed from outside because it is attached to the context/this)
var year = 2012; //Private (inside function only)
var color = "Red"; //Private (inside function only)
}
var bmw = new car("BMW");
console.log(bmw.brand); // BMW -> VISIBLE -> this.brand = brans
Solution: Using closures to create a inaccessable "private" scope.
"use strict";
(function (parent) {
(function (parent) {
var instances = {};
parent.getPrivateInstance = function (c) {
return instances[c];
};
parent.setPrivateInstance = function (c, value) {
instances[c] = value;
};
} (this));
parent.Class = function (name) {
setPrivateInstance(this, {
name: name
});
};
parent.Class.prototype.logName = function () {
console.log(getPrivateInstance(this).name);
};
})(window);
var c = new Class("test");
c.logName(); // "test"
console.log(c.name); // undefined
Caution: Memory leak
This will create a situation wherein the garbage collector will no longer clear the memory associated with the instances of Class because it they will always be referenced, which results in a memory leak.
To combat this we'll have to manually remove the reference made to the instances of Class. This can be done by adding one piece of code after the parent.setPrivateInstance section and one piece of code after the parent.Class.prototype.logName section. Those pieces of code would look like this:
parent.deleteFromMemory = function (c) {
delete instances[c];
};
parent.Class.prototype.deleteFromMemory = function () {
deleteFromMemory(c);
};
Usage
c = c.deleteFromMemory();
For a example of all the pieces working together: https://jsfiddle.net/gjtc7ea3/
Disclaimer
As this solution causes a memory leak I would personally advice against using it unless you know what you are doing, as it is very easy to make mistakes here.
Is it possible to access properties of a constructor object/function without first creating an instance from it?
For example, let's say I have this constructor:
function Cat() {
this.legs = 4;
};
And now – without creating a new cat instance – I want to know what value of legs is inside the constructor. Is this possible?
(And I'm not looking for stuff like: var legs = new Cat().legs. (Let's say the instantiation of a new Cat is super CPU expensive for some reason.))
Does something like this count?
function Cat() {
this.legs = 4;
}
var obj = {};
Cat.call(obj);
console.log(obj.legs); // 4
This is even more expensive:
console.log(parseInt(Cat.toString().match(/this\.legs\s*=\s*(\d+)/)[1]));
In your scenario, leg is an instance variable, which means that an object instance is needed in order to access it.
You can make it a pseudo-class variable (see class variable in Javascript), you should be able then to access it without calling the function (instantiating the object).
There's a hundred ways to do this, but the static default pattern below is as good as any of them:
function Cat(opts) {
var options = opts || {};
this.legs == options.legs || Cat.defaults.legs;
};
Cat.defaults = {
legs: 4
}
var myCat = new Cat({legs:3}); //poor guy
var normalNumberOfCatLegs = Cat.defaults.legs;
In short, no you can't access that variable without creating an instance of it, but you can work around it:
Global Variable
Assuming 'legs' may vary as the application runs, you may want to create a "global" variable by assigning legs to 'window', an object that will exist throughout the life of the page:
window.legs = 4; // put this at the top of your script
Then throughout the course of the application, you can change this until you're ready to use it in Cats():
window.legs = user_input;
Global Object
You could even assign an object to window, if you want Cats to have other, alterable attributes:
window.Cat = {};
window.Cat.legs = 4;
window.Cat.has_tail = true;
window.Cat.breeds = ["siamese","other cat breed"];
How to use Globals
Then, when a Cat object is created later on, you can pull the data from window to create an instance of Cat:
function Cat(){
this.legs = window.legs;
//or
this.legs = window.Cat.legs;
}
// cat.js
function Cat() {
}
Cat.prototype.legs = 4;
// somescript.js
var legs = Cat.prototype.legs
var cat = new Cat();
console.log(legs, cat.legs); // 4, 4
So I am designing a grade book interface and I have a course defined as:
<script>
course = new Object();
var name;
var gradingareas;
var finalgrade;
</script>
then later I want to create a new instance:
var gradingareas = new Array("Homework", "Classwork", "Exams");
course1 = new course("CS1500", gradingareas, 85);
I have also tried without the var in front to no avail. I get an "Uncaught TypeError: Object is not a function" I am very new to javascript so I don't even know if Im going about this the correct way. Any help is appreciated Thanks.
Your existing code:
// Creates a new, empty object, as a global
course = new Object();
// Creates three new variables in the global scope.
var name;
var gradingareas;
var finalgrade;
There is no connection between the variables and the object.
It looks like you want something more like:
function Course(name, gradingareas, finalgrade) {
this.name = name;
this.gradingareas = gradingareas;
this.finalgrade = finalgrade;
}
Then:
var course1 = new Course("CS1500", gradingareas, 85);
Note the use of a capital letter for naming the constructor function. This is a convention in the JS community.
JS is prototypical, rather than class based and if you are new to it there are advantages to learning this immediately rather than trying to mush classical inheritance models from it, however, classical inheritance is alive and well in JS.
Anyhow, to answer how you would access your variables:
course1.name works fine with the example above.
If you wanted to privatise your data you could take this approach using closure:
var Course = function(name, grade) {
// Private data
var private = {
name: name,
grade: grade
}
// Expose public API
return {
get: function( prop ) {
if ( private.hasOwnProperty( prop ) ) {
return private[ prop ];
}
}
}
};
Then instantiate a new object:
var course = new Course('Programming with JavaScript', 'A');
and start using all that private data:
course.get('name');
Of course, you'd probably want setters to manipulate that data too ;)
The code that you described does the following:
// Declares a memory variable called course and stores and object in it
var course = new Object();
// Declares three variables
var name;
var gradingareas;
var finalgrade;
These declared variables aren't automatically connected to the object. If you want these properties declared on the object you have 2 options:
Declare them as properties of the object
Declare them on the prototype of of the object
Example1: declare them as properties of the object:
// Declares a memory variable called course and stores and object in it
var course = new Object();
// Access or create new properties with . or [] operator
course.name = 'math';
course.gradingareas = 'muliple';
course['finalgrade'] = 'A'
console.log(course);
Example2: Declare them on the prototype:
// Create a constructor function
function Course (name, grade) {
this.name = name;
this.grade = grade;
}
// course is added on the prototype
Course.prototype.gradingareas = 'some gradingareas';
// the name and the grade are added on the object itself
var course = new Course ('willem', 10);
console.log(course);
To create a very simple object with constructor and default values, you can do :
//My object with constructor
var myObjectWithConstrutorFunction = {
//construtor function with default values in constructor
myConstrutor: function(Name = 'bob', Age = 18){
this.Name = name;
this.Age = age;
}
};
// instance
var myInstance = new myObjectWithConstrutorFunction.myConstrutor();
// show on console
console.log('object with constructor function: ', myInstance);
// show properties
console.log(myInstace.Name, myInstance.Age);
PS : It's a good practice create a constructor's name with the same name of the class, if you are creating a external class.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use of ‘prototype’ vs. ‘this’ in Javascript?
Object Oriented questions in Javascript
Can you please recommend which of the following is the best or their pros and cons?
Method 1
function User() {
this.name = "my name";
this.save = function() {
};
}
Method 2
function User() {
this.name = "my name";
}
User.prototype.save = function() {
}
Coming from a background in Java and PHP, I had initially struggled with the whole 'class' concept in JavaScript. Here are a few things to think about.
Construction
First, since you're likely going to be defining your classes as..
Customer = function () {}
Customer.prototype = new Person();
You will end up running into all sorts of nightmares of code if you are defining properties and methods during construction. The reason being is that a piece of code like Customer.prototype = new Person(); requires that the Person be called in the Customer constructor for true inheritance.. otherwise you'll end up having to know what the original one sets at all times. Take the following example:
Person = function (name) {
this.name = name;
this.getName = function () {return this.name}
}
Customer = function (name) {
this.name = name;
}
Customer.prototype = new Person();
Now we're going to update Person to also set whether they are 'new':
Person = function (name, isNew) {
this.name = name;
this.isNew = isNew;
this.getName = function () {return (this.isNew ? "New " : "") + this.name; }
}
Now on any 'class' that is inheriting from the Person, you must update the constructor to follow form. You can get around that by doing something like:
Customer = function () {
Person.apply(this, arguments);
}
That will call 'Person' in the scope of the new 'Customer', allowing you to not have to know about the Person construction.
Speed
Take a look at these benchmarks: http://jsperf.com/inherited-vs-assigned.
Basically, what I am attempting to prove here is that if you're creating these objects en masse, your best route is to create them on the prototype. Creating them like:
Person = function (name) {
this.name = name;
this.getName = function () {return this.name}
}
is very slow, because for every object creation, it creates a new function - it doesn't simply look up the prototype chain for the already existing one. Conversely, if you've got only a few objects that the methods are called extremely frequently on, defining them locally helps with the speed lost by looking up the prototype chain.
Shared properties
This always gets me. Let's say you've got something like the following:
Person = function () {
this.jobs = {};
this.setJob = function (jobTitle, active) {this.jobs[jobTitle] = active; }
}
Employee = function () {}
Employee.prototype = new Person();
var bob = new Employee();
bob.setJob('janitor', true);
var jane = new Employee();
console.log(jane.jobs);
Guess what? Jane's a janitor! No joke! Here's why. Since you didn't define this.jobs as being a new object on instantiation of the Employee, it's now just looking up the prototype chain until it finds 'jobs' and is using it as is. Fun, right?
So, this is useful if you want to keep track of instances, but for the most part you're going to find it incredibly frustrating. You can get around that by doing the following:
Employee = function () { Person.apply(this); }
This forces 'Person' to create a new 'this.jobs'.
Private variables
Since there's nothing that's really "private" in JavaScript, the only way you can get private variables is to create them in the constructor, and then make anything that relies on them initialize in the constructor.
Person = function () {
var jobs = {};
this.setJob = function (jobTitle, active) {jobs[jobTitle] = active; }
this.getJob = function (jobTitle) { return jobs[jobTitle]; }
}
However, this also means that you must call that constructor on every instantiation of an inherited class.
Suggestion
http://ejohn.org/blog/simple-javascript-inheritance/
This is a super basic class setup. It's easy. It works. And it'll do what you need it to do 90% of the time without having to deal with all the insanity JavaScript has to offer :)
</rant>
Best is a very subjective term.
Method 1 gives the possibility of truly private variables. e.g :
function User() {
var name = "fred";
this.getName = function () { return name;};
}
Method 2 will use less memory, as a single save function is shared by all User objects.
'Best' will be determined by your specific requirements.
JavaScript is an "Object Based" language, not a "Class Based" language. Shared behaviours, which is the class concept, are implemented by linking prototypes.
Method 1 does NOT create a class. Every time you invoke it, you create attributes and functions as defined and they are NOT shared with other "instances". If you replace this.save then only the one instance will have altered behaviour.
Method 2 implements shared behaviours. Therefore it is what people associate with classes and instances. If you replace this.save withe a different function, then all derived instances will immediately have the new behaviour.
If "best" means no memory consuming redefinitions of functions and sharing common behaviours (which is what class based programming tends to equate to) the Method 2 is the way to go.
As others have mentioned, there are two main differences:
Method 1 will create a new function for every instance of User
Method 1 will be able to access local variables in the constructor's scope
Here's an example to demonstrate these:
function User() {
var name = "my name";
this.foo = function() {
// one function per User instance
// can access 'name' variable
};
}
User.prototype.bar = function() {
// one function shared by all User instances
// cannot access 'name' variable
};
var a = new User();
var b = new User();
console.log(a.foo === b.foo); // false; each instance has its own foo()
console.log(a.bar === b.bar); // true; both instances use the same bar()