Suppose I have a function called log which simply prints the given string.
Can I refactor my code so both of these function could work?
log("needsChange").doSomethingWithTheStringBeforePrintingIt();
log("perfectStringToPrint");
You can do something similar with nested class logics:
var log = (function() {
//Class
var _log = (function() {
function _log(message) {
this.message = message;
}
_log.prototype.doSomethingWithTheStringBeforePrintingIt = function() {
this.message = this.message.split("").reverse().join("");
return this;
};
_log.prototype.capitalizeFirstWord = function() {
this.message = this.message[0].toUpperCase() + this.message.substr(1);
return this;
};
_log.prototype.print = function() {
return this.message;
};
return _log;
}());
//Instancer function
return function log(message) {
//Return instance of class
return new _log(message);
};
})();
//Test
console.log(log("needsChange")
.doSomethingWithTheStringBeforePrintingIt()
.capitalizeFirstWord()
.print(), log("perfectStringToPrint")
.print());
If you are comfortable with promises, then you can do something like this:
var logger = (function() {
//Class
var _log = (function() {
function _log(message) {
var _this = this;
this.message = message;
this.promise = null;
this.promises = [];
this.promise = Promise.all(this.promises).then(function(values) {
console.log(_this.message); // [3, 1337, "foo"]
});
}
_log.prototype.reverse = function() {
var self = this;
this.promises.push(new Promise(function(resolve, reject) {
setTimeout(resolve, 0, (function() {
self.message = self.message.split("").reverse().join("");
})());
}));
return this;
};
_log.prototype.capitalizeFirst = function() {
var self = this;
this.promises.push(new Promise(function(resolve, reject) {
setTimeout(resolve, 0, (function() {
self.message = self.message[0].toUpperCase() + self.message.substr(1);
})());
}));
return this;
};
return _log;
}());
//Instancer function
return function log(message) {
//Return instance of class
return new _log(message);
};
})();
//Test
logger("needsChange").reverse().capitalizeFirst().reverse(); //Capitalizes last letter
logger("perfectStringToPrint");
This removes the need for a .print call.
I have made a library to solve this issue
https://github.com/omidh28/clarifyjs
Related
I've been trying to learn Javascript. This is my code - I'm trying to implement a singleton - but for some reason, I get the error setMessage is not a function in the line firstInstance.setMessage("Message");. I have no idea what I'm doing wrong - any help would be greatly appreciated.
`
var mySingleton = (function () {
var instance;
var message;
function getInstance() {
if (!instance) instance = new Object();
return instance;
}
function setM (newMessage) {
message = newMessage;
return;
}
function getM() {
return message;
}
return {
createInstance:getInstance,
setMessage:setM,
getMessage:getM
}
})();
var firstInstance = mySingleton.createInstance();
var secondInstance = mySingleton.createInstance();
//set messages
firstInstance.setMessage("Message");
console.log(firstInstance.getMessage());
console.log(secondInstance.getMessage());
//change messages
secondInstance.setMessage("New");
console.log(firstInstance.getMessage());
console.log(secondInstance.getMessage());`
The setMessage and getMessage need to be on the instance you create, not in the object returned with the createInstance:
var mySingleton = (function() {
let instance;
let message;
function createInstance() {
if (!instance) instance = { setMessage, getMessage };
return instance;
}
function setMessage(newMessage) {
message = newMessage;
}
function getMessage() {
return message;
}
return { createInstance }
})();
var firstInstance = mySingleton.createInstance();
var secondInstance = mySingleton.createInstance();
firstInstance.setMessage("Message");
console.log(firstInstance.getMessage());
console.log(secondInstance.getMessage());
secondInstance.setMessage("New");
console.log(firstInstance.getMessage());
console.log(secondInstance.getMessage())
I have the following Pet and cat inherits from Pet, as follows:
function Pet(){};
Pet.prototype.run = function takeoff(cb, sec) {
setTimeout(function() {
cb();
console.log('Run');
}, sec);
};
Pet.prototype.bark = function bark(cb, sec) {
setTimeout(function() {
cb();
console.log('bark');
}, sec);
};
Pet.prototype.comeback = function comeback(cb, sec) {
setTimeout(function() {
cb();
console.log('Comeback');
}, sec);
};
var cat = new Pet();
cat.prototype = Object.create(Pet);
cat.prototype.run = function(){
var that = this;
that.run = Pet.prototype.run.call(that);
return that;
}
cat.prototype.bark = function(){
this.bark = Pet.prototype.bark.call(this);
return this;
}
cat.prototype.comeback = function(){
this.comeback = Pet.prototype.comeback.call(this);
return this;
}
console.log(cat);
cat.run().bark().return();
In this situation, the cat and Pet have the same function names. The only difference is return this is added to cat methods to make method chaining possible in cat but not Pet. However, note that I have to write the name of the function every time and set the same name to its parent's prototype. Is it possible to generalize this so that any method I specify for Pet will be duplicated in cat but yet I don't have to specify the method for cat every time?
After a discussion with guest I came up with a solution that extends each function to use a promise. The code will be executed in order and the object will be chained.
function Pet(){};
Pet.prototype.run = function run(callback) {
setTimeout(function() {
callback()
console.log('Run');
}, 1000);
};
Pet.prototype.bark = function bark(callback) {
setTimeout(function() {
callback()
console.log('Bark');
}, 500);
};
Pet.prototype.comeBack = function comeBack(callback) {
setTimeout(function() {
callback()
console.log('Comeback');
}, 750);
};
// DON'T MODIFY ANYTHING ABOVE HERE
// START ADD YOUR CODE HERE
function createChainableFunction(fun) {
var that = this;
return function() {
if(!that.promise) {
that.promise = new Promise(function(resolve, reject) {
fun.call(that, resolve);
});
}
else {
that.promise.then(function() {
that.promise = new Promise(function(resolve) {
fun.call(that, resolve);
});
});
}
return this;
}
}
function isFunction(functionToCheck) {
var getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}
function createChainable(object) {
var chainable = {
'promise': null
};
chainable.prototype = Object.getPrototypeOf(object);
for(var prop in object) {
if(isFunction(object[prop])) {
chainable[prop] = createChainableFunction.call(chainable.prototype, object[prop], prop);
}
}
return chainable;
}
var cat = createChainable(new Pet());
cat.run().bark().comeBack();
You can add a property in child classes and based on this value, you can return this.
Sample
// Parent Class
function Pet() {
this.sec = 1000
};
Pet.prototype.run = function takeoff(cb, sec) {
setTimeout(function() {
//cb();
console.log('Run');
}, sec || this.sec);
if (this.animalName) return this;
};
Pet.prototype.bark = function bark(cb, sec) {
setTimeout(function() {
//cb();
console.log('bark');
}, sec || this.sec);
if (this.animalName) return this;
};
Pet.prototype.comeback = function comeback(cb, sec) {
setTimeout(function() {
//cb();
console.log('Comeback');
}, sec || this.sec);
if (this.animalName) return this;
};
// Child class
var Cat = function() {
this.animalName = 'Cat'
}
// Linking of classes
Cat.prototype = new Pet();
// object of child class
var cat = new Cat();
cat.run().bark().comeback()
var pet = new Pet();
try {
// Chaining not allowed.
pet.run().bark().comeback()
} catch (ex) {
console.log(ex.message)
}
I need to use logic like visitor pattern and I've created new
sample which failed in visitor.visit(self); and I got error undefined is not a function,
any idea what am I missing?
var Entity = function (file,name) {
var self = this;
var name;
var type;
var log = {};
this.setName = function (name) {
this.name = name;
};
this.accept = function (visitor) {
visitor.visit(self);
};
this.getName = function () {
return name;
};
this.getType = function () {
return type;
};
this.getLog = function () {
return log;
};
};
//Start using visitor
var verifyFile = function () {
this.visit = function (file) {
alert("test");
};
};
function test(){
var file = new Entity();
file.accept(verifyFile);
};
You are injecting a function that defines a function, but your code is looking for an object that contains a function - see below
var Entity = function(file, name) {
var self = this;
var name;
var type;
var log = {};
this.setName = function(name) {
this.name = name;
};
this.accept = function(visitor) {
visitor.visit(self);
};
this.getName = function() {
return name;
};
this.getType = function() {
return type;
};
this.getLog = function() {
return log;
};
};
//Start using visitor
var verifyFile = {
visit : function(file) {
alert("test");
}
};
function test() {
var file = new Entity();
file.accept(verifyFile);
};
test()
I'm developing a small framework (in JS) and for esthetic reasons and simplicity I was wondering if there could be a way to implement something like PHP "__invoke".
For example:
var myClass = function(config) {
this.config = config;
this.method = function(){};
this.execute = function() {
return this.method.apply(this, arguments);
}
}
var execCustom = new myClass({ wait: 100 });
execCustom.method = function() {
console.log("called method with "+arguments.length+" argument(s):");
for(var a in arguments) console.log(arguments[a]);
return true;
};
execCustom.execute("someval","other");
Desired way to execute:
execCustom("someval","other");
Any ideas? Thanks.
if you are ready to use JS pattern, you can do this in following way:
var myClass = function(opts) {
return function(){
this.config = opts.config;
this.method = opts.method;
return this.method.apply(this, arguments);
};
};
var execCustom = new myClass({
config:{ wait: 100 },
method:function() {
console.log("called method with "+arguments.length+" argument(s):");
for(var a in arguments) console.log(arguments[a]);
return true;
}});
execCustom("someval","other");
jsbin
this is the best way I can think of
UPDATED VERSION (by op)
var myClass = function(opts) {
var x = function(){
return x.method.apply(x, arguments);
};
x.config = opts.config;
x.method = opts.method;
return x;
};
var execCustom = new myClass({
config:{ wait: 100 },
method:function() {
console.log("called method with "+arguments.length+" argument(s):");
for(var a in arguments) console.log(arguments[a]);
return true;
}});
execCustom("someval","other");
jsbin
Just return a function that will form the public interface:
function myClass(config)
{
var pubif = function() {
return pubif.method.apply(pubif, arguments);
};
pubif.config = config;
pubif.method = function() { };
return pubif;
}
The rest of the code remains the same.
i'm practicing with Javascript Inheritance, my first try is following code:
var base_class = function()
{
var _data = null;
function _get() {
return _data;
}
this.get = function() {
return _get();
}
this.init = function(data) {
_data = data;
}
}
var new_class = function() {
base_class.call(this);
var _data = 'test';
function _getData() {
return this.get();
}
this.getDataOther = function() {
return _getData();
}
this.getData = function() {
return this.get();
}
this.init(_data);
}
new_class.prototype = base_class.prototype;
var instance = new new_class();
alert(instance.getData());
alert(instance.getDataOther());
to that point i am really happy with my solution, but there is one problem
that i dont get resolved.
the "getDataOther" method don`t return the stored data from the base class,
because i cannot access the public "get" class from the protected "_getData" method in the new_class.
How can i get that running ?
Thanks in advance.
Ps.: Please excuse my poor English
If you comment out the this.init function (which overwrites the base_class _data field) and make the new_class's getData function just return _data, you should be able to get distinct variables.
var base_class = function()
{
var _data = null;
function _get() {
return _data;
}
this.get = function() {
return _get();
}
this.init = function(data) {
_data = data;
}
}
var new_class = function() {
var self = this; //Some browsers require a separate this reference for
//internal functions.
//http://book.mixu.net/ch4.html
base_class.call(this);
var _data = 'test';
function _getData() {
return self.get();
}
this.getDataOther = function() {
return _getData();
}
this.getData = function() {
return _data; //Changed this line to just return data
//Before, it did the same thing as _getData()
}
//this.init(_data); //Commented out this function (it was changing the base_class' data)
}
new_class.prototype = base_class.prototype;
var instance = new new_class();
alert(instance.getData());
alert(instance.getDataOther());
Your english is fine by the way :)