How to define optional parameters in Java Script - javascript

Here is my object construction,
function Employee(name, dob) {
this.Name = name;
this.DateOfBirth = new Date(dob);
}
Now, I have created an instance for this, like
var emp = new Employee("sample","12/12/12");
Its working fine when i print the output.
But, if i create the object like
var emp = new Employee(name = "sample");
or
var emp = new Employee(dob = "12/12/12");
its not working fine. In both the cases, the DateOfBirth field is invalid.
I need to define an object with optional parameters.

JavaScript does not support named optional parameters.
When you do var emp = new Employee(name = "sample");
You're declaring a name global variable, assigning sample to it and passing that to the new call.
You can use objects to accomplish similar syntax in JS:
var emp = new Employee({name:"sample"});
Where the Employee function becomes:
function Employee(options) {
this.Name = options.name;
if(options.dob !== undefined){
this.DateOfBirth = new Date(options.dob);
}
}
Worth mentioning, in practice, you often don't need an Employee class, and can simply do:
var emp = {name:"sample"};
Or:
var emp = {dob:new Date("12/12/12");}
So unless Employee grows to become a real model (and has more than just two fields) I think that you might want to consider that.

function Employee(params) {
if (typeof params != "undefined") {
this.Name = (typeof params.name != "undefined") ? params.name : "";
this.DateOfBirth = (typeof params.dob != "undefined") ? new Date(params.dob) : null;
}
}
new Employee({
name: "John",
dob: "12/12/12"
});
new Employee({
name: "John"
});
new Employee({
dob: "12/12/12"
});
or using simple statements using ||.
function Employee(params) {
params = params || {};
this.Name = params.name || "";
this.DateOfBirth = new Date(params.dob || "");
}

As a good practice, you should never leave out variables.
You can explicitly call var emp = new Employee(null, "12/12/12");
This way everything is initialized and you will not havea headaches later on.
There is also something like this, but you really need to check the values before assigning.
function Employee() {
this.Name = name;
this.DateOfBirth = new Date(dob);
}
var emp = new Employee(name = null,dob = "12/12/12");

Related

Understanding Contexts in Javascript

i'm struggling to understand how contexts work in JavaScript or specifically deriving the value of this. in my case i have Person constructor that returns an object. From my understanding the value of this depends on the way that the function is called. For instance calling the person function like this "Person()" .the value returned for this will be the window. How do i then ensure that the person values passed are exactly what is returned
function Person(personName,Title,Phone,Email,Id, picUrl, description){
var myusername = this.username;
var myTitle = this.Title;
var myPhone = this.Phone;
var myEmail = this.Email;
var myId = this.Id;
var mypicUrl = this.picUrl;
var mydescription = this.description;
return {
name: myusername,
Title: myTitle,
phoneNumber: myPhone,
Email: myEmail,
UserId: myId,
PictureUrl: mypicUrl,
Description: mydescription
}
}
function getallDetails (){
var PeopleCompleteList = [];
for (i=0; i< data.d.results.length; i++) {
if(data.d.results[i]['Name'] != null){
personName = data.d.results[i]['Name'].Name.split('|')[2];
userName = data.d.results[i]['Name']['Name'];
UserTitle = data.d.results[i]['Name']['Title'];
UserphoneNumber = data.d.results[i]['Name']['WorkPhone'];
UserEmail = data.d.results[i]['Name']['EMail'];
Id = data.d.results[i]['Name']['Id'];
picUrl= WebURL + '/_layouts/15/userphoto.aspx?size=L&accountname='+UserEmail;
description = data.d.results[i]['pozb'];
PeopleCompleteList.push(Person(personName, UserTitle, UserphoneNumber,UserEmail,Id, picUrl, description));
}
}
}//end function
As #CBroe and #Icepickle said in comments, you are not using the Person function as a constructor. You need to call your method with the new keyword. By doing so :
the this keyword inside your function will be a reference to the object you're willing to create (otherwise it would be a reference to the global object)
the function doesn't need to return anything as it implicitly returns the object referenced by this
I'd advise you read this article : MDN - the new operator.
Meanwhile, the snippet below shows what your code would look like if you used the Person function as a constructor
function Person(personName, title, phone, email, id, picUrl, description) {
// populating the object behind the 'this' reference with each argument
// if you call this method with the 'new' keyword, 'this' will be a reference to the instance you are creating
this.username = personName;
this.title = title;
this.phoneNumber = phone;
this.email = email;
this.userId = Id;
this.pictureUrl = picUrl;
this.description = description;
// if this function is called with the 'new' keyword, you don't have to return anything. the reference behind 'this' will be implicitly returned
}
function getallDetails() {
// local variable declarations are usually put on top of the function
var peopleCompleteList = [], personName, userName, userTitle, userphoneNumber, userEmail, id, picUrl, description;
for (i=0; i< data.d.results.length; i++) {
if (data.d.results[i]['Name'] != null) {
personName = data.d.results[i]['Name'].Name.split('|')[2];
userName = data.d.results[i]['Name']['Name'];
userTitle = data.d.results[i]['Name']['Title'];
userphoneNumber = data.d.results[i]['Name']['WorkPhone'];
userEmail = data.d.results[i]['Name']['EMail'];
id = data.d.results[i]['Name']['Id'];
picUrl= WebURL + '/_layouts/15/userphoto.aspx?size=L&accountname='+UserEmail;
description = data.d.results[i]['pozb'];
// adding the 'new' keyword before invoking the Person method
peopleCompleteList.push(new Person(personName, userTitle, userphoneNumber,userEmail,Id, picUrl, description));
}
}
}//end function
Couple side notes :
You forgot to use the var keyword when declaring variables in the getallDetails function. It's a bad practice as they will all be global variables and won't be cleared after the execution of the getallDetails function
Most of your variables declarations violate the JavaScript variable naming convention. I updated the snippet with proper variable names (using the camelCase notation).
In simple terms, You can say context is the place where this reside. For example:
<script>
function show() {
this.context = 'sudhir';
}
</script>
This is equivalent to
<script>
var context;
function show() {
this.context = 'sudhir';
}
</script>
Both functions are written on the global scope. So, this refers to global means scope or your context is global. Now let's see the interesting example:
<script>
function newContext() {
var a = function show() {
this.context = 'sudhir';
}
}
</script>
It's equivalent to write here like this:
<script>
function newContext() {
var context;
var a = function show() {
this.context = 'sudhir';
}
}
</script>
Here this refers to the function show which is written on the scope of newContext function. Hence, Context of this is newContext.
I will show you what I will have done.
First of all, if you create an object, you don't have to return a value.
function Person(personName,Title,Phone,Email,Id, picUrl, description){
this.personName = personName;
[...]
this.mydescription = description;
}
Then you instantiate your "class" like :
var person = new Person('David', ..., 'some description');
And access attribute like that :
console.log('Person name is', person.personName);
JavaScript "This" is about function scope, example :
function Person(personName,Title,Phone,Email,Id, picUrl, description){
this.personName = personName;
[...]
this.mydescription = description;
function someAnonymousFunction(){
console.log('Person name is', this.personName); // Person name is Undefined
// Because this is a reference to someAnonymousFunction
}
}
Javascript trick to preserve this is to stock the context in variable :
function Person(personName,Title,Phone,Email,Id, picUrl, description){
var self = this;
this.personName = personName;
[...]
this.mydescription = description;
function someAnonymousFunction(){
console.log('Person name is', self.personName); // Person name is David
// Because we use self variable instead of this here
}
}
But you have an easier way
ECMAScript 2015 includes classes syntax. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
If you care about navigator compatibility, you must use TypeScript
https://www.typescriptlang.org/
Typescript allow you to write more readable JavaScript code, especially about classes. Then, you can "compile" your code in JavaScript by choosing with version of JavaScript you want in output files.
Hope it helps,
Mickael

Creating Objects in Javascript with Constructor

I am trying this code
var mark = new Employee;
mark.name = 'Doe, Mark';
mark.dept = 'admin';
mark.projects = ['navigator'];
console.log(mark);
But the console won't show anything when i try to print it. It shows only when i use new Object. What is the problem?
You need to define Employee as a constructor function:
function Employee() {}
var mark = new Employee();
mark.name = 'Doe, Mark';
mark.dept = 'admin';
mark.projects = ['navigator'];
console.log(mark);
This will also allow you to set properties with the constructor like:
function Employee(name){
this.name = name
}
var mark = new Employee('Doe, Mark');
mark.dept = 'admin';
mark.projects = ['navigator'];
console.log(mark);

how to right choose javascript pattern

i create 2 objects:
var Documentos = new QuadForm();
var Cadastro = new QuadForm();
And initialize this objects with lot of options
Cadastro.initForm(options);
Documentos.initForm(options2);
then i try to separate the data managed by each object with getName method but after the second object, myObjectName variable is overrided.
var QuadForm;
QuadForm = function () {
this.getName = function () {
// search through the global object for a name that resolves to this object
for (var name in window)
if (window[name] == this) {
window[name] = this;
window[window[name]] = window[name];
myObjectName= name;
break;
}
},
this.initForm = function (parms) {
this.getName()
$.extend(this, parms);
if (window.myState) {
delete window.myState;
}
this.containerId = parms.formId;
this.getForm(parms);
this.workflowLabels('hide');
then i use window[myObjectName].totalRecords but as it changes to the latest object name off course cannot access data.
How can i manage this.
It's not a big problem to manage several instances, but your approach is impossible, cause you can't really find all possible instances and your code does definitely not what you expected to do.
For example you can define a variable on the constructor-object which holds all instances, and than you can use it in some cases:
var QuadForm = function (name) {
this.name = name;
QuadForm.instances.push(this);
this.showAllOtherInstances = function () {
QuadForm.instances.forEach(function (instance) {
if (instance !== this) {
console.log('name: ' + instance.name);
}
}.bind(this));
}
}
QuadForm.instances = [];
var foo = new QuadForm('foo');
var anotherFoo = new QuadForm('foo');
var bar = new QuadForm('bar');
var aThirdFoo = new QuadForm('foo');
foo.showAllOtherInstances();
/*
* Output:
*
* name: foo
* name: bar
* name: foo
*/

Append to constructor

This object constructor is the definition of a person:
var Person = function( age, name ){
this.age = age;
this.namge = name;
};
this is a line of code that will give the prototype of Person an array called "active"
Person.prototype.active = [];
The reason I am adding this to the prototype, is so that there is only one active array that every person, meaning Jim in this case: var Jim = new Person() ), SHARES the exact same active array.
From that point I want to add in every newly created person into the active array.
This is how I would do it:
var Jim = new Person(age, name);
Jim.active.push( Jim );
var Tim = new Person(age, name);
Tim.active.push( Tim );
What I expected from this, is for Tim.active[0] to be Jim and for
Jim.active[1] to be Tim.
The problem is, is that I want the active.push[ self id ] to be called
when a new Person is created, without the second line doing it. My solution for this would be modifying the Person constructor too look like this:
var Person = function( age, name ){
this.age = age;
this.namge = name;
this.active.push( this );// The constructor now adds itself to the array during initiation
};
As you can see, it puhes itself into the active array. The problem is that I want my object to do exactly this, but I want the constructor to begin like the first one I provided with this.active.push appended later in the code.
How do I expect this to be solved? My thoughts were that since the active array could be initiated anytime inside the program, that the functions constructor could somehow append this.active.push() to the end of it at right after Person.prototype.active = [] is executed.
Something that may look like:
Person.prototype.active = [];
Person.prototype.append( function(){this.active.push(this)} );
The second line would morph the first object constructor to look like the second one.
Not sure why you want this approach, perhaps it can be refactored? Probably better to have some sort of PersonMediator "class" in my opinion. But, if you want to have the prototype include an active array that has conditions, then attach some way to manage those conditions to the Person object.
var Person = function( age, name ){
this.age = age;
this.namge = name;
//checks for activation flag
this.ready();
};
Person.prototype.active = [];
Person.activate = function(){ Person.prototype.activate = true; };
Person.deactivate = function(){ Person.prototype.activate = false; };
Person.prototype.activate = false;
Person.prototype.ready = function(){
//depending on activate flag, appends to active array
if( this.activate ) this.append();
};
Person.prototype.append = function(){
//array append
this.active.push(this);
};
var Jim = new Person(10,'Jim');//not added, default flag false
//activate flag for appending
Person.activate();
var Tim = new Person(20,'Tim');//now added to the active array
console.log(Jim.active);//shows only Tim
console.log(Tim.active);//shows only Tim
That said, this is how I would manage this.
var Person = function( age, name ){
this.age = age;
this.namge = name;
};
var PersonMediator = function(){
this.alive = [];
this.removed = [];
};
PersonMediator.prototype.create = function(age, name){
var person = new Person(age,name);
this.alive.push(person);
return person;
};
PersonMediator.prototype.remove = function(person){
for(var i = 0; i < this.alive.length; i++){
if( this.alive[i] === person ){
this.alive.splice(i,1);
}
}
this.removed.push(person);
};
var pm = new PersonMediator();
var Jim = pm.create(10,'Jim');
var Tim = pm.create(20,'Tim');
console.log(pm.alive);
If you simply want to store the instantiated objects to an array, you can use an inheritance pattern like so:
var myArray = [];
function SuperClass() {
myArray.push(this);
};
function Block(name) {
this.name = name;
SuperClass.apply(this, arguments);
};
function Player(name) {
this.name = name;
SuperClass.apply(this, arguments);
};
var baller = new Player('Jim');
var blocker = new Block('Joe');
console.log(myArray); // [Player, Block]
Every time a new instance of Player or Block is instantiated, it will add it to the array.
Another pattern you may consider is having a set prototype object that you can add your prototypical methods and shared data to, and then assigning it as the prototype in your constructor function
var personPrototype = {
alive: []
}
var blockPrototype = {
alive: []
}
var Person = function(x, y){
//this creates a new object with the prototype of our personPrototype object
var o = Object.create(personPrototype);
//then we can configure / add instance-specific attributes and return the object
o.x = x;
o.y = y;
return o;
}
var Block = function(x, y){
var o = Object.create(blockPrototype);
o.x = x;
o.y = y;
return o;
}
var me = new Person(1, 2);
var square = new Block(10, 20);
// > []
me.alive
By using Object.create to create a dummy object we can effectively assign it a proper prototype. Then we can add whatever instance attributes we'd like, and return that object. This means that the personPrototype will be a proper prototype. Each instance can use instance.alive or instance.alive.push directly, since it automatically walks up the prototype chains
It also allows you to easily add any new data to the prototype of all your instances. You don't need to iterate through each instance and add prototypical methods. You can just add the method to the prototype to start and it will be accessible on all instances by default.
I find the whole approach - trying to track/store [Person] instances - questionable.
But if I was in the position of being told to do so, I'd go for an approach that is build upon a
factory module. Thus being at least able of assuring "read only access" to the list of all instances
that ever got created by the factory.
A possible implementation than might look similar to the following example:
var Person = (function (global, Object, Array, Math) {
var
array_from = ((typeof Array.from == "function") && Array.from) || (function (array_prototype_slice) {
return function (listType) {
return array_prototype_slice.call(listType);
};
}(Array.prototype.slice)),
personModule = {},
personList = [],
Person = function (config) { // constructor.
var person = this;
person.name = config.name;
person.age = config.age;
person.constructor = Object;
return person;
},
isPerson = function (type) {
return (type instanceof Person);
},
createPerson = function (age, name) { // factory.
/*
- sanitizing/validation of arguments etc. should be done right here.
- create instances only if all the conditions are fulfilled.
*/
var person = new Person({
name: name,
age : age
});
personList.push(person);
return person;
}/*,
removePerson = function (type) {
if (isPerson(type)) {
// remove person from the internal list.
}
}*/
;
//personModule.remove = removePerson;
personModule.create = createPerson;
personModule.isPerson = isPerson;
personModule.all = function () { // expose internal instance list.
return array_from(personList);
};
personModule.all.size = function () {
return personList.length;
};
(function () { // make [personModule.all] enumerable.
var
parse_float = global.parseFloat,
math_floor = Math.floor
;
this.first = function () {
return (this()[0]);
};
this.last = function () {
var list;
return ((list = this())[list.length - 1]);
};
this.item = function (idx) {
return (this()[math_floor(parse_float(idx, 10))]);
};
}).call(personModule.all);
return personModule;
}((window || this), Object, Array, Math));
var Jim = Person.create("Jim", 21);
var Tim = Person.create("Tim", 19);
console.log("Jim", Jim);
console.log("Tim", Tim);
console.log("Person.isPerson(Jim) ? ", Person.isPerson(Jim));
console.log("Person.isPerson(Tim) ? ", Person.isPerson(Tim));
console.log("Person.isPerson({name: 'Tim', age: 21}) ? ", Person.isPerson({name: 'Tim', age: 21}));
console.log("Person.all.size() : ", Person.all.size());
console.log("Person.all() : ", Person.all());
console.log("Person.all.first() : ", Person.all.first());
console.log("Person.all.last() : ", Person.all.last());
console.log("(Person.all()[1] === Person.all.item(1)) ? ", (Person.all()[1] === Person.all.item(1)));
console.log("(Person.all.first() === Person.all.item(0)) ? ", (Person.all.first() === Person.all.item(0)));

javascript object creating

I have a javascript object like this
var student = function () {
this.id = 1;
this.Name = "Shohel";
this.Roll = "04115407";
this.Session = "03-04";
this.Subject = "CSE";
};
and i have a javascript array list like this
var students = [];
now i want to push student into students, this is shown below
students.push(new student()) //no prolem
students.push(new student[id = 3]) //Problem
here second line occurs exceptions, how can i push javascript object like as c# add list, which is representing second line? thanks
You simply can't, what you can do though is accept a config as a parameter to your constructor and read it like this
var student = function (config) {
config = config || {};
this.id = config.id || 1;
this.Name = config.Name || "Shohel";
this.Roll = config.Roll || "04115407";
this.Session = config.Session || "03-04";
this.Subject = config.Subject || "CSE";
};
And call it like this
students.push(new student({id: 3}));
EDIT, PREFERRED ONE
Just as adeneo pointed out if you want to get rid of the repititive || for default values, you can use jQuery to pass them
var student = function (config) {
var defaults = {
id: 1,
Name: "Shohel",
Roll: "04115407",
Session: "03-04",
Subject: "CSE"
};
config = $.extend(defaults, config || {});
this.id = config.id;
this.Name = config.Name;
this.Roll = config.Roll;
this.Session = config.Session;
this.Subject = config.Subject;
};
Make the values that are variable parameters of the function. For example:
var Student = function (id) {
this.id = id;
// ...
};
students.push(new Student(3));
I recommend to read a JavaScript tutorial about functions:
MDN - JavaScript Guide
Eloquent JavaScript - Functions
quirksmode.org - Functions

Categories

Resources