Nodejs class with variables - javascript

I've this parser class in a file:
module.exports = function Parser() {
this.myVar = "";
var parse = function (inputString) {
this.myVar = "somethingAfterParse";
}
return {
initWithString: function(inputString) {
parse(inputString)
},
name: this.myVar
};
};
Then, say in "main" file js, I use parser in this way:
var Parser = require("./Parser.js");
var parserInstance = new Parser();
parserInstance.initWithString("somestring");
console.log("Parser var:", parserInstance.myVar);
No errors, but log print an empty name.. why?

Here's what I would do:
function Parser() {
this.myVar = "";
}
Parser.prototype.initWithString = function (inputString) {
this.myVar = "somethingAfterParse";
};
module.exports = Parser;
your approach, annotated
module.exports = function Parser() {
// public property "myVar" of any new Parser object
this.myVar = "";
// anonymous function assigned to private variable "parse"
var parse = function (inputString) {
// "this" will likely be the global object here, dangling error
this.myVar = "somethingAfterParse";
}
// return API object - unnecessary and makes debugging harder (*)
return {
// anonymous function that calls private "parse" function
initWithString: function(inputString) {
// calling parse without defining "this", definitely an error (**)
parse(inputString)
},
// the above is equivalent to and therefore better written as
// initWithString: parse,
// copy of (!) public property myVar, definitely an error (***)
name: this.myVar
};
};
When you leave out the redundant bits (and make use of the prototype chain) you end up with what I suggest above.
* I know this is a popular approach for defining the public interface of an object. Personally I don't like it very much. Returning an object from a JS constructor function effectively breaks the usefulness of the new operator:
You make inaccessible for the object's user everything that was assigned to this before inside the constructor, like your this.myVar.
You get a bag of properties with no type information. Technically this works, but it's not nice during debugging. Compare:
function A() {
this.a = "A";
return {
a: "a"
};
}
function B() {
this.b = "B";
}
new A(); // Object {a: "a"}
new B(); // B {b: "B"}
** this inside a function will refer to whatever object that function was called on (the context).
Usually dot notation does that for you: object.method() sets this to object inside method.
You however do not call the parse() function on any object. Any function called without context runs in the context of the global object (in browsers that's Window).
You would have needed to specify the context by using var self = this; earlier and parse.apply(self, arguments) inside the initWithString body.
In the end the whole "let's return an object as the API" approach makes things more difficult than they need to be.
*** Primitive types are always assigned by value in JavaScript. Just like with numbers or Booleans, you cannot reference strings. Assigning them to other variables makes copies of them.

you have to use .call or .apply
module.exports = function Parser() {
this.name = "";
var parse = function(inputString) {
this.name = "somethingAfterParse";
}
return {
initWithString: function(inputString) {
parse.call(this, inputString)
},
name: this.name
};
};

Instead of returning an anonymous object you can return a Parser type.
module.exports = function Parser() {
var self = this;
self.name = "";
self.parse = function (inputString) {
self.name = inputString + " parsed";
}
return self;
};
Then, say in "main" file js, I use parser in this way:
var Parser = require("./Parser.js");
var parserInstance = new Parser();
parserInstance.parse("something");
console.log("Parser name:", parserInstance.name); // Parser name: something parsed

Related

Set the name of a function at runtime in JavaScript

Is it possible to set the name of a function at runtime in JavaScript?
var ctor = function() {}; // Anonymous function because I don't know the name ahead of runtime.
ctor.name = 'foo'; // Pseudocode - this is effectively what I want to do
I want the above to be equivalent to:
var ctor = function foo() {};
Edit
Here is an example use-case:
function mix(fn1, fn2, name) {
var ctor = function() {};
ctor.name = name; // Vain attempt to set the name of the function.
ctor.prototype = Object.create(fn1.prototype);
Object.keys(fn2.prototype).map(function(k) {
ctor.prototype[k] = fn2.prototype[k];
});
// Return a constructor function with the prototype configured.
return ctor;
}
function Foo() {}
Foo.prototype.foo = function(){};
function Bar(){}
Bar.prototype.bar = function() {};
var Foobar = mix(Foo, Bar, 'Foobar');
console.log(new Foobar()); // ctor {bar: function, foo: function} (in Chrome) - I wanted Foobar { bar: function, foo: function }
name was a non-standard only supported by some browsers.
Now, it has been standardized in ECMAScript 6:
19.2.4.2 name
The value of the name property is an String that is descriptive of the
function. The name has no semantic significance but is typically a
variable or property name that is used to refer to the function at its
point of definition in ECMAScript code. This property has the
attributes { [[Writable]]: false, [[Enumerable]]: false,
[[Configurable]]: true }.
Anonymous functions objects that do not have a contextual name
associated with them by this specification do not have a name own
property but inherit the name property of %FunctionPrototype%.
Therefore, your code will work on browsers that don't support name, but the new property will be writable and enumerable. And on browsers that support it, your code won't work because name is not writable.
Therefore, a better equivalent code would be
Object.defineProperty(ctor, 'name', {
value: 'foo',
configurable: true
});
Disclaimer: This may be upsetting for some people who like their code to be safe and predictable.
Of course, you won't actually do this, because you're sensible, right?
function rename(fn, name) {
var fnStr = fn.toString().replace(/function/, 'function ' + name);
eval.call(window, fnStr);
return window[name];
}
var tmp = function(a, b) { return a + b; };
rename(tmp, 'add');
add(3, 4); // 7
Of course, depending on how well behaved you need to be (not very if you use eval), you could (but you won't) go one step further.
Function.prototype.rename = function(name) {
return rename(this, name);
};
Do this in actual code and people will hate you, but that's ok, because you won't.
There are a few hiccups (and probably some broken edge cases) to do with the scope in which the function was defined. Eval uses the context of this to decide which scope to operate within, so passing the window object means the renamed function will always be defined within the window object.
Fairly contrived example, but it should give you some idea of the pitfalls.
function init() {
function go() {
return 'go';
};
var ctor = function() {
return 'ctor';
};
rename(ctor, 'go');
go(); // 'go'
next();
}
function next() {
go(); // 'ctor'
}

Make object's properties available inside function

I would like to do the following.I have a code like this:
var obj = {
method : function() {}
};
var func = function() {
return method(); //method is undefined here
};
func(); // What to do here?
Is it possible to call func in a way that it will see the method inside from obj as it was given for example as a parameter. I want to use obj.method inside func, without writing 'obj.' before and without modifying func itself. Is there any hack possible to achieve this?
In other words, is it possible to force obj as a closure into func?
I tried:
with(obj) {
func();
}
But it doesn't work. Anyone, any ideas? Or is it the only option to get the body of the function as string, put 'with(obj)' inside it and then create a new function out of it?
Clarification:
Because this code will be in a helper class 'eval' is OK. Which I don't want is the modification of the function through .toString(), because browsers implement it differently.
This is a solution, using eval (MDN):
var obj = {
method : function() {console.log("it workes!");}
};
var func = function() {
return method(); //method is undefined here
};
var newfunc = (function (obj, func) {
var method = obj.method;
eval("var f = " + func.toString());
return f;
}(obj, func));
newfunc(); //it workes
Basically you're just creating a new scope with a local variable called method and re-evaluating the function body in this scope. So you're basically creating a new function with the same body. I don't really like this approach and I wouldn't recommend it, but considering your constraints, it might be the only solution.
And yes, it still requires you to write obj.method, but not inside of func. So I figured, it should be ok.
EDIT
So here is a version, in which you don't have to specify the property name manually:
var newfunc = (function (__obj__, __func__) {
for (var __key__ in __obj__) {
if (__obj__.hasOwnProperty(__key__)) {
eval("var " + __key__ + " = " + __obj__[__key__]);
}
}
eval("var __f__ = " + func.toString());
return __f__;
}(obj, func));
This also done by using eval().
Note that I changed all remaining local variables to a names containing underscores, to minimize the probability of name collisions with properties inside obj.
Note also that not all valid property names are valid variable names. You could have an object like this:
var obj = {
"my func": function () {}
}
But if you would use this object you would generate a syntax error with the above method, because it would try to evaluate:
var my func = ...
As apsillers said in the comment section, it gets even worse if you don't have control over the properties of obj. In this case you shouldn't use eval at all, because you would make cross-site scripting attacks very easy (example from apsillers):
var obj = {
"a; alert('xss'); var b": function () {}
}
would evaluate to 3 different statements:
var a;
alert('xss');
var b = function () {};
This is not possible unless you define method separately:
var obj = {
method : function() {}
},
method = obj.method;
// rest of code
This is because the method reference inside func() assumes the window. namespace; thus, without modifying func() itself, it can't be done sanely.
More clarified version based on basilikum's answer, and I've found a simplification with 'with':
var obj = {
method : function() { return "it workes!"; }
};
var func = function() {
return method(); //method is undefined here
};
(function (obj, func) {
with(obj) {
eval("var __res__ = (" + func.toString() + ")()");
}
return __res__;
}(obj, func));
>> "It workes!"

Javascript: Function - Return an Object will invalid this.variable

I m using javascript. Declaring a instance variable "this.variable" will work until my function will return an object. Return of an String, Number doesnt affect it. In the case of returning an object the instance variable doesnt work anymore and become "undefined". Please can you help me! (Look for a sample at http://jsfiddle.net/woko/vE4rq/2/ tested under recent versions of firefox & chrome )
function Funct() {
this.varfunc = "this ist a instance";
return false;
}
var f = new Funct();
console.log(f.varfunc);
function FunctReturnobj() {
this.varfunc = "this ist a instance + return an object";
return {};
}
var fr = new FunctReturnobj();
console.log(fr.varfunc)
this in the scope of a function is DOMWindow.
this in the scope of an object is the object.
You're using constructors in a wrong way. Constructors shouldn't return anything themselves. You can use the prototype property to declare "class"/object methods or you can set them in the constructor like you already do:
function Constructor(value) {
this.variable = value;
}
var obj = new Constructor('test');
obj.variable; // -> Returns 'test';
Same way you can declare methods of you object:
function Constructor(value) {
this.variable = value;
this.say = function(something) {
return "I say: " + something;
};
}
Or the prototype way:
function Constructor(value) {
this.variable = value;
}
Constructor.prototype.say = function(something) {
return "I say: " + something;
};
Of course this a generic and kinda bad example, but you probably get the point :)
The new operator will create a new object and apply the function on it - this in the function scope refers to that object.
But when the function is called without new, or contains a return statement, it won't be executed as a "constructor". this will point to the execution context, usually the window object.

Forcing the context

I have this class where I have a private property and a public method for access:
Person = function () {
this.Name = "asd";
var _public = new Object();
_public.Name = function (value) {
if (value == undefined) { //Get
return this.Name
} else {
this.Name = value; //Set
}
};
return _public;
};
I want to force the context in _public.Name for access a this.Name.
I know the technique of closure, but I want to see if I can force a context.
I found a technique to do it, extend object Function:
Function.prototype.setScope = function (scope) {
var f = this;
return function () {
f().apply(scope);
}
}
And my class becomes:
Person = function () {
this.Name = "asd";
var _public = new Object();
_public.Name = function (value) {
if (value == undefined) {
return this.Name
} else {
this.Name = value;
}
}.setScope(this);
return _public;
};
So I can force correctly the context, but I can not pass value and can not, however, return this.Name.
Not
f().apply(scope);
just
f.apply(scope);
(No () after f.) You want to use the apply function on the function f object, not call the function f and access apply on its return value.
To also pass on the arguments that your function in setScope receives, add this:
f.apply(scope, arguments);
arguments is an implicit argument to all functions, which is a pseudo-array of the actual arguments passed to the function at runtime. apply accepts any array-like thing as its second parameter to specify the arguments to use when calling the underlying function.
I'd also have it return the return value:
return f.apply(scope, arguments);
So setScope becomes:
Function.prototype.setScope = function (scope) {
var f = this;
return function () {
return f.apply(scope, arguments);
}
}
Live example
Note that the usual name for this function, and the name it has in the new ECMAScript5 standard, is bind (Section 15.3.4.5; ECMAScript5's bind also lets you curry arguments, which isn't done by this implementation). setScope is a particularly unfortunate name, because it doesn't set the scope, it sets the context.
Having said all that, there's no reason you need setScope in your Person constructor. You can just do this:
Person = function () {
var self = this;
this.Name = "asd";
var _public = new Object();
_public.Name = function (value) {
if (value == undefined) {
return self.Name;
} else {
self.Name = value;
}
};
return _public;
};
Live example
But using bind (aka setScope) can be useful in places where you don't want a new closure over the context in which you're doing it.
Off-topic: The way you're specifying Person will break certain things people might expect to work, such as:
var p = new Person();
alert(p instanceof Person); // Expect "true", but in your case will be "false"
...because you're replacing the object new created for you, but returning a different object out of your constructor (which overrides the default).
Rather than creating a new object and returning that in your constructor, allow the object constructed for you by new to be the object (and thus the Person relationship is maintained), but you can still get truly private variables and use accessors:
function Person() {
// Private variable
var name = "asd";
// Accessor function
this.Name = function(value) {
if (typeof value === "undefined") {
return name;
}
name = value;
};
}
Live example
As you can see, this is dramatically simpler, and it preserves the instanceof relationship. Note that we're not qualifying our references to name within Name at all, and so we're using the local variable in the constructor call in which our Name function, which closes over it, was created.
I've also taken the liberty there of giving the constructor function a name, because I'm not a fan of anonymous functions. I should have given the accessor a name as well:
function Person() {
// Private variable
var name = "asd";
// Accessor function
this.Name = Person_Name;
function Person_Name(value) {
if (typeof value === "undefined") {
return name;
}
name = value;
}
}
Off-topic 2: The overwhelming convention in JavaScript code is to use initial caps on function names only for constructor functions (like Person), and not on other kinds of functions (like Name). You're free to do whatever you like, of course, but I thought I'd mention the convention, as it makes it easier for other people to read your code.
Worth noting: All of these techniques result in every single Person object having its own copy of the accessor function. If there are going to be a lot of these objects, that could be a memory issue. If there are only going to be a few, that's fine.
First thing, I think the correct way to go about this is the "closure" method, as the syntax is easier and simpler to understand and makes more sense and most object oriented code written in Javascript is written that way. Another thing to note is that in your method, the "private" member can be accessed from outside by accessing Person.Name (instead of (new Person()).Name).
That being said, it seems that you want something like Prototype.JS's bind method, which allows you to bind a function reference as a method call to a specific object, and also passes all the arguments correctly (including allowing preloaded arguments).
Look at Prototype.JS source for the complete implementation, but a simple implementation of this semantic might look like this:
Function.prototype.bind = function(context) {
var callee = this;
var args = Array.prototype.slice.call(arguments,1);
return function() {
var newargs = args.concat(Array.prototype.slice.call(arguments,0));
return callee.apply(context, newargs);
};
};
It is difficult to understand what you are trying to achieve. But if I guess that you are trying to create a Person class with a name method to get/set the person's name, here is my suggestion:
function Person() {
this._name = undefined; // not required but is better than assigning a fake name
return this;
}
Person.prototype.name = function( _name ) {
if ( _name === undefined ) return this._name; // get
return this._name = _name; // set
}
Note that I have defined the name function with a lower case first letter. This is standard practice in JavaScript where only constructors are usually capitalized. To use this class you do:
person = new Person();
person.name( "Ermes Enea Colella" );
alert( person.name ); // displays "Ermes Enea Colella"
There is no need to bind any context with this method, so you may be looking for something else. If you can clarify your need, I'll be happy to edit my answer.
I hope this helps.

javascript singleton question

I just read a few threads on the discussion of singleton design in javascript. I'm 100% new to the Design Pattern stuff but as I see since a Singleton by definition won't have the need to be instantiated, conceptually if it's not to be instantiated, in my opinion it doesn't have to be treated like conventional objects which are created from a blueprint(classes). So my wonder is why not just think of a singleton just as something statically available that is wrapped in some sort of scope and that should be all.
From the threads I saw, most of them make a singleton though traditional javascript
new function(){}
followed by making a pseudo constructor.
Well I just think an object literal is enough enough:
var singleton = {
dothis: function(){},
dothat: function(){}
}
right? Or anybody got better insights?
[update] : Again my point is why don't people just use a simpler way to make singletons in javascript as I showed in the second snippet, if there's an absolute reason please tell me. I'm usually afraid of this kind of situation that I simplify things to much :D
I agree with you, the simplest way is to use a object literal, but if you want private members, you could implement taking advantage of closures:
var myInstance = (function() {
var privateVar;
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
},
publicMethod2: function () {
// ...
}
};
})();
About the new function(){} construct, it will simply use an anonymous function as a constructor function, the context inside that function will be a new object that will be returned.
Edit: In response to the #J5's comment, that is simple to do, actually I think that this can be a nice example for using a Lazy Function Definition pattern:
function singleton() {
var instance = (function() {
var privateVar;
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
},
publicMethod2: function () {
// ...
}
};
})();
singleton = function () { // re-define the function for subsequent calls
return instance;
};
return singleton(); // call the new function
}
When the function is called the first time, I make the object instance, and reassign singleton to a new function which has that object instance in it's closure.
Before the end of the first time call I execute the re-defined singleton function that will return the created instance.
Following calls to the singleton function will simply return the instance that is stored in it's closure, because the new function is the one that will be executed.
You can prove that by comparing the object returned:
singleton() == singleton(); // true
The == operator for objects will return true only if the object reference of both operands is the same, it will return false even if the objects are identical but they are two different instances:
({}) == ({}); // false
new Object() == new Object(); // false
I have used the second version (var singleton = {};) for everything from Firefox extensions to websites, and it works really well. One good idea is to not define things inside the curly brackets, but outside it using the name of the object, like so:
var singleton = {};
singleton.dothis = function(){
};
singleton.someVariable = 5;
The ES5 spec lets us use Object.create():
var SingletonClass = (function() {
var instance;
function SingletonClass() {
if (instance == null) {
instance = Object.create(SingletonClass.prototype);
}
return instance;
}
return {
getInstance: function() {
return new SingletonClass();
}
};
})();
var x = SingletonClass.getInstance();
var y = SingletonClass.getInstance();
var z = new x.constructor();
This is nice, since we don't have to worry about our constructor leaking, we still always end up with the same instance.
This structure also has the advantage that our Singleton doesn't construct itself until it is required. Additionally, using the closure as we do here prevents external code from using our "instance" variable, accidentally or otherwise. We can build more private variables in the same place and we can define anything we care to export publically on our class prototype.
The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object. 1
(function (global) {
var singleton;
function Singleton () {
// singleton does have a constructor that should only be used once
this.foo = "bar";
delete Singleton; // disappear the constructor if you want
}
global.singleton = function () {
return singleton || (singleton = new Singleton());
};
})(window);
var s = singleton();
console.log(s.foo);
var y = singleton();
y.foo = "foo";
console.log(s.foo);
You don't just declare the singleton as an object because that instantiates it, it doesn't declare it. It also doesn't provide a mechanism for code that doesn't know about a previous reference to the singleton to retrieve it. The singleton is not the object/class that is returned by the singleton, it's a structure. This is similar to how closured variables are not closures, the function scope providing the closure is the closure.
I am just posting this answer for people who are looking for a reliable source.
according to patterns.dev by Lydia Hallie, Addy Osmani
Singletons are actually considered an anti-pattern, and can (or.. should) be avoided in JavaScript.
In many programming languages, such as Java or C++, it's not possible to directly create objects the way we can in JavaScript. In those object-oriented programming languages, we need to create a class, which creates an object. That created object has the value of the instance of the class, just like the value of instance in the JavaScript example.
Since we can directly create objects in JavaScript, we can simply use
a regular object to achieve the exact same result.
I've wondered about this too, but just defining an object with functions in it seems reasonable to me. No sense creating a constructor that nobody's ever supposed to call, to create an object with no prototype, when you can just define the object directly.
On the other hand, if you want your singleton to be an instance of some existing "class" -- that is, you want it to have some other object as its prototype -- then you do need to use a constructor function, so that you can set its prototype property before calling it.
The latter code box shows what I've seen JS devs call their version of OO design in Javascript.
Singetons are meant to be singular objects that can't be constructed (except, I suppose, in the initial definition. You have one, global instance of a singleton.
The point of using the "pseudo constructor" is that it creates a new variable scope. You can declare local variables inside the function that are available inside any nested functions but not from the global scope.
There are actually two ways of doing it. You can call the function with new like in your example, or just call the function directly. There are slight differences in how you would write the code, but they are essentially equivalent.
Your second example could be written like this:
var singleton = new function () {
var privateVariable = 42; // This can be accessed by dothis and dothat
this.dothis = function () {
return privateVariable;
};
this.dothat = function () {};
}; // Parentheses are allowed, but not necessary unless you are passing parameters
or
var singleton = (function () {
var privateVariable = 42; // This can be accessed by dothis and dothat
return {
dothis: function () {
return privateVariable;
},
dothat: function () {}
};
})(); // Parentheses are required here since we are calling the function
You could also pass arguments to either function (you would need to add parentheses to the first example).
Crockford (seems to) agree that the object literal is all you need for a singleton in JavaScript:
http://webcache.googleusercontent.com/search?q=cache:-j5RwC92YU8J:www.crockford.com/codecamp/The%2520Good%2520Parts%2520ppt/5%2520functional.ppt+singleton+site:www.crockford.com&cd=1&hl=en&ct=clnk
How about this:
function Singleton() {
// ---------------
// Singleton part.
// ---------------
var _className = null;
var _globalScope = null;
if ( !(this instanceof arguments.callee) ) {
throw new Error("Constructor called as a function.");
}
if ( !(_className = arguments.callee.name) ) {
throw new Error("Unable to determine class name.")
}
_globalScope = (function(){return this;}).call(null);
if ( !_globalScope.singletons ) {
_globalScope.singletons = [];
}
if ( _globalScope.singletons[_className] ) {
return _globalScope.singletons[_className];
} else {
_globalScope.singletons[_className] = this;
}
// ------------
// Normal part.
// ------------
var _x = null;
this.setx = function(val) {
_x = val;
}; // setx()
this.getx = function() {
return _x;
}; // getx()
function _init() {
_x = 0; // Whatever initialisation here.
} // _init()
_init();
} // Singleton()
var p = new Singleton;
var q = new Singleton;
p.setx(15);
q.getx(); // returns 15
I stole this from CMS / CMS' answer, and changed it so it can be invoked as:
MySingleton.getInstance().publicMethod1();
With the slight alternation:
var MySingleton = { // These two lines
getInstance: function() { // These two lines
var instance = (function() {
var privateVar;
function privateMethod () {
// ...
console.log( "b" );
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
console.log( "a" );
},
publicMethod2: function () {
// ...
privateMethod();
}
};
})();
singleton = function () { // re-define the function for subsequent calls
return instance;
};
return singleton(); // call the new function
}
}

Categories

Resources