var createworker = function() {
var workcount;
var input;
(function() {
workcount = 0;
console.log("hello");
}());
var task1 = function() {
workcount += 1;
console.log("task1" + workcount);
};
var task2 = function(a) {
workcount += 1;
input = a;
console.log("task2" + workcount + "variable" + a);
};
var task3 = function() {
console.log(input);
};
return {
job1: task1,
job2: task2,
job3: task3
};
}
var worker = new createworker();
worker.job1();
worker.job2(2);
worker.job3();
var worker1 = createworker();
worker1.job1();
worker1.job2(2);
worker1.job3();
Both work same. Then why to use new and when to use it?
Both work same.
They reason they both work the same is that you're returning an object from createworker. That overrides the work that new did.
new is used with constructor functions. It does this:
Creates a new object backed by the object the constructor function's prototype property points ot
Calls the constructor function with this referring to that new object
In the normal case, the result of new functionname is a reference to the object that new created. But, if the constructor function returns a non-null object reference, the result of the new expression is that object instead. It's that "but" that's happening in your createworker example.
So your version of createworker doesn't need new, because of the way it's written.
And doing it that way is absolutely fine; in fact, there are people who always do it that way. If you wanted to use new with createworker, here's a version designed to be used that way (renamed CreateWorker, because by convention constructor functions are capitalized):
var CreateWorker = function() {
var workcount;
var input;
(function() { // Side note: This function is pointless. Just move
workcount = 0; // <− this line
console.log("hello"); // <− and this one
}()); // ...out into the body of `createworker`/`CreateWorker`
// Note we assign to properties on `this`
this.job1 = function() {
workcount += 1;
console.log("task1" + workcount);
};
this.job2 = function(a) {
workcount += 1;
input = a;
console.log("task2" + workcount + "variable" + a);
};
this.job3 = function() {
console.log(input);
};
// Note we aren't returning anything
};
Related
In creating the interface for a Stack in JavaScript - using a functional style as opposed to prototypal or pseudoclassical style, should the below "storage" and "count" variables be someInstance.storage and someInstance.count, respectively so they can be accessed on an instance of this stack later?
With the variables declared as they are now, once we create and instance of the stack by executing the function, we lose access to see what the count (size) and the storage (properties in the stack).
What's the best means of declaring properties (not methods) we need to access later using a functional creation pattern?
Thanks!
var Stack = function(){
var someInstance = {};
var storage = {};
var count = 0;
someInstance.push = function(value){
storage[count++] = value;
};
someInstance.pop = function(){
if(count){
var popped = storage[--count];
}
delete storage[count];
return popped;
};
someInstance.size = function(){
return count;
};
return someInstance;
};
var stack = Stack();
The private variables mentioned below can be studied in javascript of closure.
reference: https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures
var Stack = function(){
// PUBLIC
var someInstance = {};
// PRIVATE: Attach _ to private variables. (just implicit rule.)
var _storage = {};
var _count = 0;
someInstance.push = function(value){
storage[_count++] = value;
};
someInstance.pop = function(){
if(_count){
var popped = storage[--_count];
}
delete storage[_count];
return popped;
};
someInstance._size = function(){
return _count;
};
// if you assign public variable, you can access!!!
someInstance.size = _size;
someInstance.count = _count;
return someInstance;
};
var stack = Stack();
You can add getters and setters for them in the someInstance object (courtesy of closures) like so:
Object.defineProperty(someInstance, "count", {
get: function() {
return count;
},
set: function(value) {
count = value;
}
});
You can omit the set part if you want to be able to just get the value and not set it.
Example:
var Stack = function(){
var someInstance = {};
var storage = {};
var count = 0;
Object.defineProperty(someInstance, "count", {
get: function() {
console.log("getter called");
return count;
},
set: function(value) {
console.log("setter called");
count = value;
}
});
return someInstance;
};
var stack = Stack();
console.log(stack.count);
stack.count = 55;
console.log(stack.count);
Whether storage and count should be someInstance.storage and someInstance.count depends on how you want the user of this instance to work it. That's a bit opinion based. My opinion is that a stack shouldn't allow the user to change the count with something like someInstance.count = 10 because that would break it.
Personally I would make count and storage private which will prevent accidental bugs that could happen with direct access. A nice way to do this is to capture them in a closure and provide a getter for count so you can still read the count, but can't change it. Something like:
var Stack = function(){
let storage = [], count = 0; // these will be caputured as a closure
return {
// the returned object will have push, pop, and a count getter
push(v) {
storage.push(v)
count++
},
pop() {
if (count) count--
return storage.pop()
},
get count(){ // allow reading of count
return count
}
}
}
var stack = Stack();
stack.push("hello");
stack.push("goodby");
stack.count = 10 // has no effect
console.log(stack.count) // count is still 2
console.log(stack.pop())
console.log(stack.count)
console.log(stack.pop())
console.log(stack.count)
Of course, since this mostly uses an array, you could do away with the count variable altogether and just use storage.length
var Stack = function(){
let storage = [], count = 0; // these will be caputured as a closure
return {
// the returned object will have push, pop, and a count getter
push(v) { //method
storage.push(v)
count++
},
pop: function() {
if (count) count--
return storage.pop()
},
get count(){ // allow reading of count
return count
},
get insidebox(){ // allow reading of count
return storage
},
callprice:function(cnt){
var price=cnt*100;
return price;
}
}
}
Stack.prototype.price2 = function() {
return "testpr";
};
var sb = Stack();
console.log(sb.count);
sb.push('paint');
console.log(sb.insidebox);
console.log(sb.count);
sb.push('Sharee');
console.log(sb.insidebox);
sb.push('Shirt');
sb.push('shoes');
console.log(sb.insidebox);
sb.pop();
console.log(sb.insidebox);
console.log(sb.count);
console.log(sb.callprice(sb.count));
function Person(first, last, age, eye) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eye;
}
Person.prototype.nationlity='Indian';
Person.prototype.fullname = function() {
return this.firstName + " " + this.lastName
};
var myFather = new Person("Lalji", "Maurya", 50, "blue");
console.log(myFather.fullname());
console.log(myFather);
console.log(myFather.nationlity);
var myBrother = new Person("Ashish", "Maurya", 28, "black");
console.log(myBrother.fullname());
console.log(myBrother);
console.log(myBrother.nationlity);
I want to be able to call sub-functions that work with private data. Currently I have this:
var myFunction4 = function() {
this.secret1 = 0;
this.secret2 = 0;
var that = this;
this.iterate1 = function(){
return that.secret1++;
}
this.iterate2 = function(){
return that.secret2++;
}
this.addSecrets = function(){
return that.secret1 + that.secret2;
}
return {
iterate1: this.iterate1,
iterate2: this.iterate2,
addSecrets: this.addSecrets,
}
};
The bad thing about this is that to call one of the methods, I have to do:
myFunction4().iterate1();
Which executes myFunction4() every single time I want to access a method. Not only is this inefficient, but it resets secret1 each time so I can't iterate it. I've tried using the new operator, but that exposes secret1 and secret2, and it messes up the ability to nest functions deeply.
var myFunction3 = function() {
this.secret1 = 0;
this.secret2 = 0;
this.iterate1 = function(){
return this.secret1++;
}
this.iterate2 = function(){
return this.secret2++;
}
this.addSecrets = function(){
return this.secret1 + this.secret2;
}
};
var f3 = new myFunction3();
f3.secret1; // exposes the secret!
See the console logs at the bottom of this JSFiddle for more examples.
How can I have a function with both private and public vars/methods which retain their values and don't need to be called multiple times?
While the other answers are absolutely fine and correct, there is one more issue to consider when emulating OOP behaviour in javascript.
The function execution context issue will bite us hard when we will try to use a public method as a e.g. async. callback.
The magical this will point to a different object then we expect in the OOP world.
Of course there are ways to bind the context but why to worry about this after we define the 'class' in a non OOP js ;)
Here is a simple solution to this: Do not use this. Let the closure refactor this out ;)
var myFunction4 = function() {
// we could inherit here from another 'class' (object)
// by replacing `this` with e.g. `new SuperClass()`
var that = this;
// 'private' variables
var secret1 = 0;
var secret2 = 0;
// 'public' variables
that.somePublicVar = 4;
// 'private' methods
var somePrivateMethod = function(){
secret2 = 77;
that.somePublicVar = 77;
}
// 'public' methods
that.iterate1 = function(){
return secret1++;
}
that.iterate2 = function(){
return secret2++;
}
that.addSecrets = function(){
return secret1 + secret2;
}
return that;
};
var f = new myFunction4();
console.log( f.iterate1() ); // 0
console.log( f.iterate1() ); // 1
console.log( f.secret1 ); //undefined
console.log( f.somePublicVar ); //4
Try that (closures power!):
var myFunction3 = function() {
var secret1 = 0;
var secret2 = 0;
this.iterate1 = function(){
return secret1++;
}
this.iterate2 = function(){
return secret2++;
}
this.addSecrets = function(){
return secret1 + secret2;
}
};
var f3 = new myFunction3();
now only the methods are exposeds
Edited version:
If you don't wanna execute the main function every time you call sub-method, you can change a bit your approach and use the power of IIFE (immediately-invoked function expression)
var myFunction4 = (function() {
var secret1 = 0;
var secret2 = 0;
var iterate1 = function(){
return secret1++;
}
var iterate2 = function(){
return secret2++;
}
var addSecrets = function(){
return secret1 + secret2;
}
return {
iterate1: iterate1,
iterate2: iterate2,
addSecrets: addSecrets
}
}());
Then you can use this:
myFunction4.iterate1();
myFunction4.iterate2();
myFunction4.addSecrets();
Hope this helps you
I generally only use the factory pattern to create objects unless I absolutely need to have the performance benefits of prototypical inheritance.
Using the factory pattern also means you don't have to deal with the ever changing value of this in different contexts.
var factory = function() {
// internal private state
var state = {
secret1: 0,
secret2: 0
}
function iterate1(){
return state.secret1++;
}
function iterate2(){
return state.secret2++;
}
function addSecrets(){
return state.secret1 + state.secret2;
}
function __privateMethod() {
// this is private because it's not on the returned object
}
// this is the public api
return {
iterate1,
iterate2,
addSecrets
}
}
// create a secret module
var secret = factory()
console.log(
secret.iterate1(), // 0
secret.iterate2(), // 0
secret.addSecrets(), // 2
secret.secret1, // undefined
secret.secret2 // undefined
)
// you can even create more with the same factory
var secret2 = factory()
Why don't you try Revealing Module Pattern
var myFunction4 = function() {
var secret1 = 0,
secret2 = 0,
iterate1 = function(){
return secret1++;
},
iterate2 = function(){
return secret2++;
},
addSecrets = function(){
return secret1 + secret2;
};
// public functions and properties
return {
iterate1: iterate1,
iterate2: iterate2,
addSecrets: addSecrets,
}
}();
myFunction4.iterate1(); // is available
myFunction4.secret2; // is private and not available outside of myFunction4
Hope it helps
A basic pattern:
var myFunction = function() {
var that = this;
var secret1 = 0;
var secret2 = 0; // private
this.public1 = 0; // public
this.iterate1 = function(){
return secret1++;
}
this.iterate2 = function(){
return secret2++;
}
this.addSecrets = function() { // public
return privateMethod();
}
var privateMethod = function() { // private
return secret1 + secret2;
}
return this; // return function itself!
};
var myFn = new myFunction();
myFn.public1 // 0
myFn.secret1 // undefined
myFn.addSecrets();
I recommend you to read the excellent Learning JavaScript Design Patterns by Addy Osmani.
What I understand from your explanation as per your second snippet is that you need a sharedPrivate among the instantiated objects. You can not do this with classical object creation patterns like constructor, factory or module. This is possible by taking a private variable under closure in the prototype of the constructor so that it doesn't get reset each time an object is created and at the meantime the instantiated objects are provided with necessary methods to access, modify and share it privately.
function SharedPrivate(){
var secret = 0;
this.constructor.prototype.getSecret = function(){return secret}
this.constructor.prototype.setSecret = function(v){ secret = v;}
this.constructor.prototype.incrementSecret = function(){secret++}
}
var o1 = new SharedPrivate();
var o2 = new SharedPrivate();
console.log(o1.getSecret()); // 0
console.log(o2.getSecret()); // 0
o1.setSecret(7);
console.log(o1.getSecret()); // 7
console.log(o2.getSecret()); // 7
o2.incrementSecret()
console.log(o1.getSecret()); // 8
And another method of getting a similar result would be
function SharedPrivate(){
var secret = 0;
return {getS : function(){return secret},
setS : function(v){secret = v},
incS : function(){secret++}
};
}
sharedProto = SharedPrivate(); // secret is now under closure to be shared
var o1 = Object.create(sharedProto); // sharedProto becomes o1.__proto__
var o2 = Object.create(sharedProto); // sharedProto becomes o2.__proto__
o1.setS(7); // o1 sets secret to 7
console.log(o2.getS()); // when o2 access it secret is still 7
o2.incS(); // o2 increments the secret
console.log(o1.getS()); // o1 can access the incremented value
I have multiply functions which are using the same cycle code and i'm wondering is it possible to simplify the code by having one cycle function so i could execute the code just by calling wanted function names.
Now:
for(var i=0;i<all;i++){ someFunction(i) }
Need:
cycle(someFunction);
function cycle(name){
for(var i=0;i<all;i++){
name(i);
}
}
I tried to do this by using "window" and i get no error but the function is not executed.
var MyLines = new lineGroup();
MyLines.createLines(); // works
MyLines.addSpeed(); // doesn't work
var lineGroup = function(){
this.lAmount = 5,
this.lines = [],
this.createLines = function (){
for(var i=0,all=this.lAmount;i<all;i++){
this.lines[i] = new line();
}
},
this.addSpeed = function (){
// no error, but it's not executing addSpeed function
// if i write here a normal cycle like in createLines function
// it's working ok
this.linesCycle("addSpeed");
},
this.linesCycle = function(callFunction){
for(var i=0,all=this.lAmount;i<all;i++){
window['lineGroup.lines['+i+'].'+callFunction+'()'];
}
}
}
var line = function (){
this.addSpeed = function (){
console.log("works");
}
}
window['lineGroup.lines['+i+'].'+callFunction+'()'];
literally tries to access a property that starts with lineGroups.lines[0]. Such a property would only exist if you explicitly did window['lineGroups.lines[0]'] = ... which I'm sure you didn't.
There is no need to involve window at all. Just access the object's line property:
this.lines[i][callFunction]();
i get no error but the function is not executed.
Accessing a non-existing property doesn't generate errors. Example:
window[';dghfodstf0ap9sdufgpas9df']
This tries to access the property ;dghfodstf0ap9sdufgpas9df, but since it doesn't exist, this will result in undefined. Since nothing is done with the return value, no change can be observed.
Without a name space use:
window["functionName"](arguments);
SO wrap it up and use it thus:
cycle(someFunction);
function cycle(name){
for(var i=0;i<all;i++){
window[name](i);;
}
}
With a namespace, include that:
window["Namespace"]["myfunction"](i);
Note that this is likely a bit of overkill but using a function to make a class object (you can google the makeClass and why it is/could be useful) you can create instances of the object.
// makeClass - By Hubert Kauker (MIT Licensed)
// original by John Resig (MIT Licensed).
function makeClass() {
var isInternal;
return function (args) {
if (this instanceof arguments.callee) {
if (typeof this.init == "function") {
this.init.apply(this, isInternal ? args : arguments);
}
} else {
isInternal = true;
var instance = new arguments.callee(arguments);
isInternal = false;
return instance;
}
};
}
var line = function () {
this.addSpeed = function () {
console.log("works");
};
};
var LineGroup = makeClass();
LineGroup.prototype.init = function (lineNumber) {
this.lAmount = lineNumber?lineNumber:5,
this.lines = [],
this.createLines = function (mything) {
console.log(mything);
var i = 0;
for (; i < this.lAmount; i++) {
this.lines[i] = new line();
}
},
this.addSpeed = function () {
console.log("here");
this.linesCycle("addSpeed");
},
this.linesCycle = function (callFunction) {
console.log("called:" + callFunction);
var i = 0;
for (; i < this.lAmount; i++) {
this.lines[i][callFunction]();
}
};
};
var myLines = LineGroup();
myLines.createLines("createlines");
myLines.addSpeed();
//now add a new instance with 3 "lines"
var newLines = LineGroup(3);
newLines.createLines("createlines2")
console.log("addspeed is a:" + typeof newLines.addSpeed);
console.log("line count"+newLines.lAmount );
newLines.addSpeed();
I lately was experimenting with the object serialization in JavaScript. I have already been looking through some of the questions concerning the serialization and deserialization of predefined object in Javascript, but I am looking for a more general solution. An example of this would be:
function anObject(){
var x = 1;
this.test = function(){return x;};
this.add = function(a){x+a;};
}
var x = new anObject();
x.add(2);
console.log(x.test());
>>> 3
var y = deserialize(serialize(x));
console.log(y.test());
>>> 3
Is there a way to serialize this object and deserialize it, such that the deserialized object still have access to the local variable x without the use of the prototype of that object (like in this solution)?
I have already tried by just storing the function as a string and evaluating it again, but then the state of an object can not be saved.
What you are trying to do is not possible without code introspection and code re-writing which I think is not a good idea. However, what about something like this?
function AnObject() {
var x = 1;
this.x = function () { return x; };
this.addToX = function (num) { x += num; };
this.memento = function () {
return { x: x };
};
this.restoreState = function (memento) {
x = memento.x;
};
}
var o = new AnObject();
o.addToX(2);
o.x(); //3
var serializedState = JSON.stringify(o.memento()),
o = new AnObject();
o.restoreState(JSON.parse(serializedState));
o.x(); //3
However, please note that having priviledged members comes at a great cost because you lose the benefits of using prototypes. For that reason I prefer not enforcing true privacy and rely on naming conventions such as this._myPrivateVariable instead (unless you are hiding members of a module).
Thanks for the responses. While the answer from plalx works perfectly for specific objects, I wanted to have something more general which just works for any object you throw at it.
Another solution one can use is something like this:
function construct(constructor, args, vars) {
function Obj() {
var variables = vars
return constructor.apply(this, args);
}
Obj.prototype = constructor.prototype;
return new Obj();
}
function addFunction(anObject, aFunction, variables) {
var objectSource = anObject.toString();
var functionSource = aFunction.toString();
objectSource = objectSource.substring(0,objectSource.length-1);
var functionName = functionSource.substring(9, functionSource.indexOf('('));
var functionArgs = functionSource.substring(functionSource.indexOf('('), functionSource.indexOf('{')+1);
var functionBody = functionSource.substring(functionSource.indexOf('{')+1, functionSource.length);
return objectSource + "this." + functionName + " = function" +
functionArgs + "var variables = " + variables + ";\n" + functionBody + "}";
}
function makeSerializable(anObject) {
var obj = JSON.stringify(anObject, function(key, val) {
return ((typeof val === "function") ? val+'' : val);
});
var variables = [];
while(obj.indexOf("var") > -1) {
var subString = obj.substring(obj.indexOf("var")+3, obj.length-1);
while (subString[0] == " ")
subString = subString.replace(" ", "");
var varEnd = Math.min(subString.indexOf(" "), subString.indexOf(";"));
var varName = subString.substring(0, varEnd);
variables.push(varName);
obj = obj.replace("var","");
}
var anObjectSource = addFunction(anObject,
function serialize(){
var vars = [];
console.log("hidden variables:" + variables);
variables.forEach(function(variable) {
console.log(variable + ": " + eval(variable));
vars += JSON.stringify([variable, eval(variable)]);
});
var serialized = [];
serialized.push(vars);
for (var func in this){
if (func != "serialize")
serialized.push([func, this[func].toString()]);
}
return JSON.stringify(serialized);
},
JSON.stringify(variables));
anObject = Function("return " + anObjectSource)();
var params = Array.prototype.slice.call(arguments);
params.shift();
return construct(anObject, params, variables);
}
This allows you to serialize all elements of any object, including the hidden variables. The serialize() function can then be replaced by a custom string representation for the hidden variables, which can be used when deserializing the string representation to the object.
usage:
function anObject(){
var x = 1;
var y = [1,2];
var z = {"name": "test"};
this.test = function(){return x;};
this.add = function(a){x+a;};
}
var test = makeSerializable(anObject)
test.serialize()
>>>["[\"x\",1][\"y\",[1,2]][\"z\",{\"name\":\"test\"}]",["test","function (){return x;}"],["add","function (a){x+a;}"]]
i think i did not understand javascript module pattern.
I just create this module:
var mycompany = {};
mycompany.mymodule = (function() {
var my = {};
var count = 0;
my.init = function(value) {
_setCount(value);
}
// private functions
var _setCount = function(newValue) {
count = newValue;
}
var _getCount = function() {
return count;
}
my.incrementCount = function() {
_setCount(_getCount() + 1);
}
my.degreeseCount = function() {
_setCount(_getCount() - 1);
}
my.status = function() {
return count;
}
return my;
})();
var a = mycompany.mymodule;
var b = mycompany.mymodule;
console.debug(a, 'A at beginning');
console.debug(a, 'B at beginning');
a.init(5);
b.init(2);
console.log('A: ' + a.status()); // return 2 (wtf!)
console.log('B: ' + b.status()); // return 2`
Where is the mistake?
I thought that my code would have returned to me not 2 value, but 5.
What's the reason?
a and b are the exact same objects.
var a = mycompany.mymodule;
var b = mycompany.mymodule;
What you want to do is create two different objects which have the same prototype. Something similar to this:
mycompany.mymodule = (function () {
var my = function () {};
my.prototype.init = function (value) {
_setCount(value);
};
my.prototype.incrementCount = ...
// ...
return my;
}());
a = new mycompany.mymodule();
b = new mycompany.mymodule();
a.init(5);
b.init(2);
For more info, research "javascript prototypal inheritance"
In JavaScript, objects are passed by reference, not copied.
To explain further, here is a simplified version of your code:
var pkg = (function () {
var x = {};
return x;
}());
var a = pkg;
var b = pkg;
You do not create two separate objects but only reference the object pointed at by pkg from both a and b. a and b are exactly the same.
a === b // true
This means that calling a method on a you are ultimately doing the same to b (it points to the same object—x.)
You don't want to use the module pattern for this. You want the usual constructor+prototype.
function Pkg() {
this.count = 0;
};
Pkg.prototype.init = function (count) { this.count = count; };
var a = new Pkg();
var b = new Pkg();
a === b // false
a.init(2);
a.count === 2 // true
b.count === 2 // false
Here is a good read about module pattern.