I've created an ashx page which is going to serve me an XML document full of basic user information. I'm not sure which is the best way to go about creating and populating my custom javascript object. I've seen them created in two ways:
function User() {
this.Id;
this.FirstName;
this.LastName;
this.Title;
}
and
var User2 = {
Id: null,
FirstName: null,
LastName: null,
Title: null
}
I could populate each of these by doing something like:
//first object
User.Id = 1
//second object
User2.FirstName = 'John'
Is one method of creating the object better than the other?
Edit: A year and a half later I saw that this question got the popular badge, so I just wanted to mention that today I am using Crockford's module pattern.
You cannot access the first object's properties without instantiation, i.e. using the new keyword:
var myUser = new User() ;
document.write(myUser.id) ;
The second object is an object literal which is accessible without instantiation as it is already instantiated when parsed.
The difference comes into play if you want use prototypical inheritance to create a new object on basis of the old one. Writing an object literal is probably easier to understand and the more appropriate pattern if you have a rather compact code base. However, prototyping comes in handy if you want to create a new object by augmenting an existing object with another object without having to rewrite the object getting augmented:
ipUser.prototype = User ;
ipUser.ip = "128.0.0.1" ;
In your case this difference might not seem striking, but you have to imagine how much redundant code you would get if you would create another object literal for every meager addition to the original object.
Look into the Mozilla Developer Center's page on JavaScript Objects if you have additional questions, it's outlined pretty well: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference:Global_Objects:Object .
Hth
You don't have to create an object with empty values first. JavaScript doesn't need place holders and can add properties and methods dynamically at any time. That is, this would suffice as well:
var User2 = {};
User2.Id = 1;
User2.FirstName = 'John';
//...Etc.
If you're just concerned about storing data I'd use this form (the object literal, ie. your second method).
Update: You could also make things a bit easier and create a function that creates user objects for you:
function createUser(id, firstname, lastname, title) {
return {
Id: id,
FirstName: firstname,
LastName: lastname,
Title: title
};
}
var User2 = createUser(1, 'John', 'Smith', 'Manager');
The first is a typical object, known from OOP. You can add functions to act on the attributes like this (assuming there is a function getFullName):
var u = new User();
u.getFullName();
The second one is just an associative array, in which strings are mapped to values.
In JavaScript the boundary between the two is not as strict as in ohter programming languages.
Related
Don't do it
This question has some comments with a low opinion of the very notion of reconstructing the objects. The commenters either couldn't or wouldn't explain why they thought it was a bad idea, but since asking I have come the to same conclusion. Here's why.
If you think about MVVM, the purpose of having a model and a view-model is to separate behaviour from data. This is kind of funny, because the point of object-orientation is to combine them. But in a distributed world, the data has to be shipped around. If your code and data are all munged together then you have to either invent MVVM or keep de- and re-constructing objects.
The code to de- and re-construct objects is a testing and maintenance time-sink you don't need, and introduces two failure modes. Don't do it. Have a method-less class to hold the state and a stateless class that operates on the method-less class. This is the essence of MVVM, and really nothing more than application of Memento pattern.
Memento (283)
Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.
Design Patterns, Gamma et al, 1995
Original question
The data of my view models is passed back and forth between client JS and server Web APIs as JSON.
It is well understood that JSON.stringify(object) serialises only members that have a non-null value that is not a Function. Thus, JSON.parse(JSON.stringify(someObject)) will remove all the methods from the object.
My current implementation has each graph node implemented as a Typescript class with Serialise and Deserialise methods. JQuery.ajax calls a Web API and implicitly parses the resultant JSON into a DAG of object definitions, each of which has a Type property indicating which type of class it was prior to serialisation. I have a map of constructors indexed by name and the appropriate constructor is retrieved and the data passed as the constructor parameter.
Depending on type there may be children; if so things proceed recursively down the graph.
I have been wondering whether, rather than copy all the property values, I couldn't just assign an appropriate prototype. Bring the mountain to Mahomed, you might say. This would eliminate quite a bit of clutter in my codebase.
As I write it occurs to me that I could use $.extend, but I'm progressively weeding jQuery out of my codebase so this would be a retrograde step.
Is there any known peril in my proposition of diddling the prototype?
Does anyone have a better idea? Other than $.extend, I mean. Something TypeScripty, by preference.
It has been observed in comments that assigning the prototype means the constructor is never called. This is irrelevant. The object state is already set up, all that is required is to make the methods available.
I recently built object with methods which content could be serialized and then reconstructed.
I simply added an argument which could take a JSON object and assign it to itself.
Example using plain object:
function myObject() {
this.valueA = 1;
this.valueB = 2;
this.valueC = 3;
this.add = function() {
return this.valueA + this.valueB + this.valueC;
};
}
var o = new myObject();
console.log(o.add());
console.log(JSON.stringify(o));
If you serialized this you would get:
{"valueA":1,"valueB":2,"valueC":3}
Now, to reconstruct this you can add a Object.assign() to the object like this taking the argument and merge it with self:
function myObject(json) {
this.valueA = 0;
this.valueB = 0;
this.valueC = 0;
this.add = function() {
return this.value1 + this.value2 + this.value3;
};
Object.assign(this, json); // will merge argument with itself
}
If we now pass the parsed JSON object as argument it will merge itself with the object recreating what you had:
var json = JSON.parse('{"valueA":1,"valueB":2,"valueC":3}')
function myObject(json) {
this.valueA = 0;
this.valueB = 0;
this.valueC = 0;
this.add = function() {
return this.valueA + this.valueB + this.valueC;
};
Object.assign(this, json); // will merge argument with itself
}
var o = new myObject(json); // reconstruct using original data
console.log(o.add());
If you now have children via array you simply repeat the process recursively down the chain.
(A bonus is that you can also pass options this way).
I'm building a JS metadata generator so we have access to strongtyped entities and properties. I do this by generating a Metadata prototype and adding a Entities prototype into it. I then populate that prototype with all of our entities such as Metadata.Entities._Customer which returns 'Customer' as a string and Metadata.Entities.Customer which lists all of its properties.
However the issue becomes when you have nested properties like entity.entityRef.property. What I want to call is Metadata.Entities.Customer.Category.Description and have it return 'Category.Description'.
If possible I want to avoid generating every possible route since our metadata can get very extensive, so I was hoping to know if javascript is capable of fishing out the last bit without having to give it as a string literal (it kinda voids the purpose of wanting to make it more strongtyped) in which case I can simply have Metadata.Entities.Customer.Category point to Metadata.Entities.Category to access its properties.
var Metadata= {
Entities: {}
};
Metadata.Entities._Customer = 'Customer';
Metadata.Entities._Category = 'Category';
Metadata.Entities.Customer = {};
Metadata.Entities.Category = {};
Metadata.Entities.Customer.Category = Metadata.Entities.Category;
Metadata.Entities.Cateogry.Description = 'Description';
Use the following simple example:
var MyObject = {
name: '',
object_id: '',
awesomeFunction: function() { console.log('awesome'); }
};
Now, this is fine until I think about prototypal inheritance. Say i now want to inherit from this object:
var child_object = Object.create(MyObject);
This instantly causes problems because the child object has not specified the name and object_id properties which will therefore be taken from the parent object (prototype). And there is no native way to enforce that child objects are created with their own versions of these, right?
Is this understanding correct?
If so, am i thinking about inheritance in javascript incorrectly?
Should objects be treated as containers for functions instead?
And there is no native way to enforce that child objects are created with their own versions of these, right?
If you want all the instances to have those attributes, by default, then you should not inherit but construct them. The normal way to do this would be
function Parent(name, id) {
this.name = name;
this.id = id;
}
function Child(name, id) {
Parent.call(this, name, id);
}
Now, when you create an instance of Child, they will have their own version of name and id. Also, you can assign values to them while creating them itself.
Let's say there is a simple object literal which name will never change:
var car = {
wheels : 4,
construct : function() {
var that = this;
setTimeout(function() {
console.log(that.wheels);
console.log(car.wheels);
}, 500);
}
};
My question is: Which way is better? Referencing by the object's name or creating a new variable (which may take some time and memory and probbaly must be done in multiple functions)?
Within the object, you should always refer to the object via this (or a copy of it, e.g. that, if required) to prevent the following breakage:
var car = ...
// do stuff
car = undefined; // or anything else, perhaps by a code hacker in the JS console
// class is now broken
You should treat the variable name that happens to have been given to your object on the outside as unknown to you, and subject to change.
Someone else might call it something else, there might be multiple names, the name might suddenly point at some other object altogether. Such variables are for the benefit of the "owners" of references to the object, and not for the object itself.
I have decided (whether bravely or foolishly remains to be seen) decided to increase my javascript skills beyond the use of alerts and I've
been looking at using javascript business objects with the hope of creating a useful library of objects that I can then manipulate with JSON or XML
further on down the line.
The basic concepts are straightforward enough but I can't seem to find an example anywhere of how to expose a property of an object that is a collection of
a different type of object.
For instance if I have a "Department" object I would like to have an "Employees" property which is a collection of "Employee" objects.
I'm from a .Net background so I might be coming at this with the completely wrong mindset here but if I am I'd like to learn the right way to approach this.
Is the concept still applicable in javascript, can a property of a javascript object be a collection of another type of object? Does the concept of a collection even exist (I'd like to be able to enumerate through the collection too) or should I be thinking in terms of arrays or something else?
Here is some pseudo code which should illustrate what I'm aiming for:
function Department (Name)
{
this.DepartmentName=Name;
this.Employees = null; // How do I initialise a property to be a collection of Employee objects?
}
function Employee(FirstName, Surname)
{
this.EmployeeName = Firstname + ' ' + Surname;
}
Department.prototype.addEmployee = function (Firstname, Surname)
{
//In here I want to create an Employee object and add it to an
//'Employees' property of the department object
}
There is no real "list of objects of a specific type" in JavaScript. You seem to just want an array, which is a "collection" (basically an object) with numeric keys and values which can be everything (JavaScript is dynamic, so there is no easy way to force a collection to contain only items of one type, but you should never need to anyway):
function Department (Name)
{
this.DepartmentName = Name;
this.Employees = []; // empty array
}
Then in the prototype function, you can:
create a new instance (object) of type Employee
add it to this.Employees
Like:
Department.prototype.addEmployee = function (Firstname, Surname)
{
// adds to the end of the array
this.Employees.push(new Employee(Firstname, Surname));
};
You can access the Employee objects like this.Employees[0], etc.
Don't forget the semicolon at the end of the prototype function. It's a function expression, and it's good practice to terminate function expressions with a semicolon. Function declarations (like for Department and Employee), on the other hand, do not need those. The difference is that the prototype function is used as an expression in the assignment statement.
Moreover, CapitalCase is usually used for constructors (Employee); regular variable names are usually names in camelCase.