Javascript function parameter to be used as constructor - javascript

I'm trying to do a reusable module, with lesser code. Will something like this work? (Well, not really going to work, it's just an example to give you the idea)
var test = function(foo) {
var bar = new foo(); // The keyword foo is from the parameter
}
The parameter is actually a string. So if I passed "FooBar", a FooBar object will be created.
It's like saying:
var test = function('FooBar') {
var bar = new 'FooBar'();
}
Are there other elegant ways which would fit the solution I'm looking for?
Many thanks!

If foo is a constructor function, then your code will work just fine (I'm curious why you didn't just try it). You can see it work here: http://jsfiddle.net/jfriend00/yT6Vk/.
If you want advise on other/better ways to solve your problem, you'll have to back up and describe more about what you're really trying to do.
There are alternate ways of doing things like this such as factory functions or a single function that examines it's arguments to decide which type of object to create, but without more info on exactly what problem you're trying to solve, we can't really say whether other methods are better/worse than what you already have.
A disadvantage of this method is that you haven't allowed for any arguments to be passed to the constructor.

I would use Douglas Crockford's method
var booze = {
beer:'ale',
wine: 'pinot noir'
}
//test(X)
var createObject = function(o){
function F () {}
F.prototype = o
return new F()
}
var test = function () {
var x = createObject(booze)
return x;
}
test()

Related

What is a factory function?

I understand that this question may be considered broad. I am currently learning Javascript and throughout the process I've stumbled upon different terms of functions that are thrown around such as: factory function, and constructor functions regarding to object-oriented programming. I am having trouble understanding these terms and finding the distinction among them, although based upon my personal understanding; factory functions are basically regular functions, or am I not seeing the bigger picture in all this? Anyways I hope my brief description of this concept can somehow help in some sort of way.
Constructor function can be called with the new keyword. By calling new JavaScript creates a new object and returns this object.
let constructorFunction = new IAmConstructorFunction();
and its definition:
function IAmConstructorFunction() {
this.foo = "1";
this.bar = "2";
}
A factory function can be called like regular function:
let objByFactory = someFactoryFunction();
and its definition:
function factoryFunction() {
let obj = {
foo : "1",
bar : "2",
someMethod: function() {
/* code of function here */
}
};
return obj;
}

Performance issue when assigning the same function to multiple variables in JavaScript

[Edited] Important! Function is treated as object, not value. So this question is invalid because it is based on a wrong assumption. This edit serves as a note to avoid confusing anyone who read this question.
Let's say I have a function expression of foo
var foo = function() {
return this.member;
}
and I have the following class and instantiate many objects of it with "foo" as the callback function.
var simpleClass = function(callback) {
this.member = "I am an instance variable";
this.callback = callback;
}
var a = new simpleClass(foo);
var b = new simpleClass(foo);
var c = new simpleClass(foo);
.
.
.
Since in JavaScript arguments are passed by value, we are copying the value([Edited]actually it should be object) of foo to a, b, c and other variables' callback. If my understanding is correct, then foo will be copied n times, each occupying certain memory space for each object.
Base on this understanding, I have some performance questions regarding this situation:
Does copying functions to multiple variables harm the performance?
Since each copies of "foo" as simpleClass object's "callback" occupies space, if there are really many simpleClass object(e.g. in a DOM library I have thousands of DOM objects which has the same function css()), will it harm the performance significantly? Or most JavaScript engine has mechanism to tackle this situation and it generally won't harm at all?
In situation where potentially hundreds or thousands of object will be created. Is it always a good practice to put those shared functions to the prototype of an object?
Since all the object instance share the same class prototype, if we put the "foo" function to the prototype of simpleClass, then there should have only one copy of the "foo" and every object instance will just execute the prototype copy of "foo" when needed. Is this a good practice we should follow?
I try to search for similar keywords but couldn't find the right wordings to find the solution to this problem. Please correct my wordings if I make anything unclear. And of course if I have any misunderstandings please correct me too. I appreciate everyone's help.
I don't understand this well enough to give you an authoritative answer but I can say this:
then foo will be copied n times, each occupying certain memory space for each object.
This is incorrect. foo is a variable pointing to a function. foo is not the function, if you did var bar = foo, bar now also points to the function, the same function. So the function is not copied. A reference to the function is assigned to this.callback.
In situation where potentially hundreds or thousands of object will be created. Is it always a good practice to put those shared functions to the prototype of an object?
What is and isn't good practise in JavaScript is up for debate. Some people like to use class/prototype, other people use object literals. It's definitly true though that prototype can help reduce the memory footprint of your application. See it like this: if you're using prototype you're giving the JavaScript engine more information about the object, ie. that your object is similar to all these other objects. The JavaScript engine should be able to make optimizations based on that. I can't say too much about the exact numbers, it might vary wildly per vendor.
Your code sample is equivalent to this:
function foo() {}
function myClass() {
this.foo = foo;
}
var instance = new myClass();
If you used prototypes you'd write:
function myClass() {}
myClass.prototype.foo = function () {};
var instance = new myClass();
If you used object literals you'd have:
function foo() {};
function create_myClass() {
return {
foo: foo
};
}
var instance = create_myClass();
In all the cases above the function foo is never copied. In these cases below you do create a new copy of foo every time:
function myClass() {
this.foo = function () {}; // new copy every time
}
var instance = new myClass();
function create_myClass() {
return {
foo: function () {}; // new copy every time
};
}
As for performance. This is the tip I always give: don't start optimizing until you run into a measurable problem. Always measure with real data. Additionally, if you think your way of doing things is good then it's likely that JavaScript engine vendors will optimize for that method.
In javascript reference is copied not the object itself so you can't assign the value to callback to change the function from inside constructor. You your code all those object will share the function, look at this snipet:
var foo = function() {
return this.member;
}
var simpleClass = function(callback) {
this.member = "I am an instance variable";
this.callback = callback;
}
var a = new simpleClass(foo);
var b = new simpleClass(foo);
alert(a.callback === b.callback ? 'shared' : 'not shared');

Use of Function class in JavaScript

I have seen usage like var f1=new Function(); but no more than that. Tried to search in Google regarding Function-class but nothing returned what I needed.
What is its significance?
Please suggest me how and when to use it. If possible give me some genuine link to study about it.
Best practice suggest you should never use a base type constructor functions. In a lot of case, use new with a base type will break the usage of typeof.
But, new Function() is valid JavaScript. Just not recommended, and not useful in most cases (var a= function() {} is equivalent).
Not that you can use the Function constructor as an eval call like so new Function('var a = 1; return a + a;'). But this can be dangerous, so use carefully.
There isn't necessarily a beneficial reason to use new Function() since you could simply create a blank function like so:
var f1 = function () {
// my function code here;
};
// calling the function
f1();
Each one will have the prototypes of Function attached to it either way.
new Function() (also new Array(), etc) should typically be avoided since it has to eval.
Technically, there really isn't a difference between these two bits of JavaScript (other answers have covered this):
var f1 = new Function();
and
var f1 = function () { };
What you can do, however, is use Function to check against the types of your variables:
var f1 = 'cat';
console.log(typeof(f1) === typeof(Function)); // false
var f2 = function () { return 'cat'; };
console.log(typeof(f2) === typeof(Function)); // true
Function objects created with the Function constructor are parsed when the function is created. This is less efficient than declaring a function and calling it within your code, because functions declared with the function statement are parsed with the rest of the code.
from MDN

Putting arrays into custom objects

I am attempting to build my first custom object and it looks something like this:
function URLObject()
{
this.syllables = new Array();
etc...
this.AddtoSyllables = AddtoSyllables;
function AddtoSyllables(AWord)
{
var SylCount = this.syllables.length;
alert("This is SylCount: " + SylCount);
}
}
var myobj = new URLObject();
myobj.AdtoSyllables("text");
The execution of the above code results in the JS engine printing out the following:
This is Sylcount: NAN
-or-
This is SylCount: undefined.
I have looked at information in Head First Javascript, in the Javascript bible, and on various JS websites. All of them cover in exhaustive detail the use of arrays of objects, but none of them discuss arrays within objects.
And yet I am doing something wrong here and I do not know what. Can anyone help?
Here you go:
function URLObject()
{
this.syllables = [];
etc...
}
URLObject.prototype.addToSyllables = function(aWord) {
var SylCount = this.syllables.length;
alert("This is SylCount: " + SylCount);
}
var myobj = new URLObject();
myobj.adtoSyllables("text");
.prototype adds the function declared after it to every object constructed by the constructor function. (in your case every object that was instantiated by new URLObject())
Firstly, the code as posted actually works for me on Chrome and Firefox; so this must depend on the JavaScript engine, or else there's something funky going on.
Update: I suspect what may be confusing you is some separate call to AddtoSyllables (in code you haven't shown us) where suddenly this.syllables is no longer defined. This is where the behavior of this can get confusing. I've created a jsFiddle to hopefully explain how it works a bit better for you.
http://jsfiddle.net/J3tUb/
That said, it is often very possible to write code like this without having to use this (or the prototype) at all. For instance:
function createURLObject() {
// Use closed-over locals instead of attaching properties.
var syllables = new Array();
function AddToSyllables(AWord) {
// Since syllables is closed over, it is accessible here
// (but WON'T be accessible outside this scope).
syllables.push(AWord);
return syllables.length;
}
// Expose whatever functionality you want to be "public"
// in the returned object.
return {
AddToSyllables: AddToSyllables
};
}
var myObj = createURLObject();
myObj.AddToSyllables("text");
It is, of course, valuable to understand JavaScript's quirky (and surprising, to most developers coming from other languages) behavior with respect to this. That said, once you do understand it, I suspect you will find that it can often be avoided altogether.
you need to do this :
function URLObject()
{
var that = this;
that.AddtoSyllables = AddtoSyllables;
function AddtoSyllables(AWord)
etc...
Like this you can add method and attributes to one object.
The issue you are having is that the function AddtoSyllables is not a member function or method of the URLObject. It is just a nested function with no object attachments, so all usages of this will result in returning the dom window object. The correct way of declaring the AddtoSyllables function is this:
function URLObject()
{
//...
}
URLObject.prototype.AddtoSyllables = function (AWord)
{
var SylCount = this.syllables.length;
alert("This is SylCount: " + SylCount);
}
To explain the reasons of the behavior in the question, I'd like to clarify that objects in javascript are treated like a map, dictionary or a key-value pair (use the term what suits you best). Using the syntax x.y = value; is equivalent putting the value value into the map x with key y. Having the code:
this.AddtoSyllables = AddtoSyllables;
function AddtoSyllables(AWord)
{
var SylCount = this.syllables.length;
alert("This is SylCount: " + SylCount);
}
adds the AddtoSyllables function as an entry to the object this points to.
The code
myobj.AdtoSyllables(...)
is equivalent to
myobj["AdtoSyllables"](...) // now a retreiaval operation
or even
var fn = myobj["AdtoSyllables"];
fn (...);
Inside the AdtoSyllables function, this is used. Against common expectations, it is not a pointer to the myobj.
The cause of this is that AddtoSyllables is treated as a static method of the URLObject class (as OOP guys would understand it), or even a loose static function (like in C). To make JS treat it like a member of the URLObject object (an instance method to OOP guys), JS must be told to do so. This is achieved through the URLObject.prototype.AddtoSyllables = .... which equivalents to declaration of an instance method.
From an alternative point of view:
function foo() { /* some code using `this` */ }
var bar = {};
var baz = {};
bar.foo = foo; // same as bar["foo"] = foo;
baz.foo = foo; // same az baz["foo"] = foo;
In the above code, this usages inside foo will neither point to bar, nor baz. At the same time bar.foo will point to the very same instance as baz.foo, for foo is also an object.

Can you name an instance the same as its constructor name?

Can you name an instance the same as its constructor name?
var myFunc = new function myFunc(){};
?
As it seems, this replaces the Function Object with the new instance... which means this is a good Singleton.
I haven't seen anyone using this, so I guess, there are downsides to this that I am unaware of...
Any thoughts?
YES...
However, it does look weird that you're creating a named function but never refer to it by name.
The more common pattern(s) I've seen are
function MyClass(){
this.val = 5;
};
MyClass.prototype.getValue = function() {
return this.val;
}
MyClass = new MyClass();
But when people do that I wonder why they don't just use a literal object
var MyClass = {
val: 5,
getValue: function() {
return this.val;
}
}
And I would even prefer to use the module pattern here
var MyClass = (function(){
var val = 5;
return {
getValue: function() {
return val;
}
};
})();
Disclaimer
Now whether the singleton pattern should be used, that's another question (to which the answer is NO if you care about testing, dependency management, maintainability, readability)
http://accu.org/index.php/journals/337
Why implementing a Singleton pattern in Java code is (sometimes) considered an anti-pattern in Java world?
As it seems, this replaces the Function Object with the new instance
No, it does not replace anything. The name of a function expression (that's what you have) is only accessible inside the function itself, not outside of it. It would be exactly the same as if you omit the name:
var myFunc = new function(){};
In general, if you don't want certain symbols accessible, just don't make them global. Define those symbols inside a function and just return whatever you want to make accessible, e.g:
var myobj = (function() {
function Foo() {};
// do whatever
return new Foo();
}());
However, if you just want to create a single object, it is often easier to use an object literal:
var myobj = {};
There is no reason to use a constructor function if you only want to create a single instance from it. If you want to establish inheritance, you can use Object.create [MDN]

Categories

Resources