Any way to call an object as a function? - javascript

I want to be able to do something like
var x = {};
x.something = function(y){
console.log(y);
};
x("hi"); // Call it without using .something
Is this possible? Any ideas?

var x = function(str) {
return x.something(str);
};
x.something = function(str) {
console.log(str);
};

Functions are objects, so you could do something like:
var x = function(y) {
console.log(y);
}
x.prop = function(){ return 'This works'; };
x('hi');
console.log(x.prop());

Related

method chaining failed in javascript

I'm trying to train myself to write chaining function but got error of
Cannot read property 'minus' of undefined(…)
What's wrong with my code?
var math = function(){
var result = 0;
var add = function(param){
result += param;
};
var minus = function(param){
result -= param;
};
var print = function(){
console.log(result)
};
return {add:add, minus: minus, print:print};
}
var calculator = math();
var result = calculator.add(5).minus(1).print();
console.log(result)
You need to return the object (this) in this case, to "chain" like you are expecting
You print() also doesn't return anything so result is always undefined.
var math = function(){
var result = 0;
var add = function(param){
result += param;
return this;
};
var minus = function(param){
result -= param;
return this;
};
var print = function(){
console.log('result: ' + result);
// print doesnt return anything, it needs to if you want to assign anything by calling it
return result;
};
return {add:add, minus: minus, print:print};
}
var calculator = math();
var result = calculator.add(5).minus(1).print();
console.log(result)
You can also store a reference to the object returned.
var math = function() {
var result = 0;
var add = function(param) {
result += param;
return math;
};
var minus = function(param) {
result -= param;
return math;
};
var print = function() {
console.log(result)
};
var math = {
add: add,
minus: minus,
print: print
};
return math;
}
var calculator = math();
calculator.add(5).minus(1).print();

Generic function?

I'm trying to figure out the answer to this question:
Without using Javascript's bind function, implement the magic function so that:
var add = function(a, b) { return a + b; }
var addTo = add.magic(2);
var say = function(something) { return something; }
var welcome = say.magic('Hi, how are you?');
addTo(5) == 7;
welcome() == 'Hi, how are you?';
I think I need to use call or apply but I just don't know, if someone could point me in the right direction or provide some literature it would be much appreciated.
You can use closure, and apply function
Function.prototype.magic = function(){
var self = this;
var args = Array.from(arguments);
return function(){
return self.apply(null, args.concat(Array.from(arguments)));
}
}
var add = function(a, b) { return a + b; }
var addTo = add.magic(2);
var say = function(something) { return something; }
var welcome = say.magic('Hi, how are you?');
console.log(addTo(5) == 7);
console.log(welcome() == 'Hi, how are you?');
Also you can look to Polyfill for bind function on MDN
Please see below code:
Object.prototype.magic = function (message) {
alert(message);
}
var add = function (a, b) { return a + b; }
var addTo = add.magic(2);
var say = function (something) { return something; }
var welcome = say.magic('Hi, how are you?');
addTo(5) == 7;
welcome() == 'Hi, how are you?';

JavaScript function chaining using the singleton pattern

I have a small piece of code written like in below.
var MY = MY || {};
MY.Farm = (function () {
var add = function(x){
console.log(x)
return this + this;
};
return {
add: function(x){
return add(x);
}
}
});
On a separate file I create sheep an instance of MY.Farm
var sheep = new MY.Farm()
I want to be able to call the function like the following with an output 6
sheep.add(3).add(2).add(1)
Any ideas how I can achieve this? What are the changes required to the MY.Farm snippet to accommodate this?
Thanks in advance.
Something like this
var MY = MY || {};
MY.Farm = (function () {
var x=0;
return {
add: function(newX){
if(typeof(newX) !="undefined") {
x+=newX;
return this;
}
return x;
}
}
});
var sheep = MY.Farm();
console.log( sheep.add(2).add(4).add());
http://jsfiddle.net/7q0143er/
You're not too far off. The trick is you need to keep track of the value somewhere, like in a private variable, and add needs to return this. Finally, you need a way to get the value out when you're done:
MY.Farm = function () {
var total = 0;
return {
add: function(x) {
total += x;
return this;
},
value: function() {
return total;
}
};
};
var sheep = new MY.Farm();
sheep.add(3);
console.log(sheep.value()); // => 3
console.log(sheep.add(1).add(2).value()); // => 6

Extending a function

Let's say I have a function like this:
function foo(){
var myValue = 5;
var myOtherValue = 1;
return {
getValue: function(){
return [myValue, myOtherValue];
}
}
}
Is there a way I can extend/overwrite this function somehow without touching the original function so that when I call getValue() I get [SOME OTHER VALUE I CHOOSE, myOtherValue]?
If not, can I do it at the instance level?
var myFoo = new foo();
myFoo.getValue = function(){
return [0, myOtherValue]; // how to I access myOtherValue?
}
If you don't want to modify foo, you can do this:
function foo(){
var myValue = 5;
var myOtherValue = 1;
return {
getValue: function(){
return [myValue, myOtherValue];
}
}
}
var myFoo = new foo();
//move getValue to _getValue
myFoo._getValue = myFoo.getValue;
//do custom getValue
myFoo.getValue = function(){
return [0, myFoo._getValue()[1]];
}
function foo(){
var myValue = 5;
var myOtherValue = 1;
return {
getValue: function(){
return [myValue, myOtherValue];
}
}
}
var myFoo = new foo();
var storeOriginal= myFoo.getValue;
myFoo.getValue = function(){
//your code
storeOriginal();
}
You can't.
myOtherValue is only defined in the scope of foo.
You could have to rewrite to something like this:
function foo(){
var myValue = 5;
return {
myOtherValue: 1,
getValue: function(){
return [myValue, this.myOtherValue];
}
}
}
Then you could do:
var myFoo = new foo();
myFoo.getValue = function(){
return [0, myFoo.myOtherValue];
}
function foo() {
.. original stuff ..
}
var hidden_foo = foo;
function decorator() {
var internal = hidden_foo();
// here is the proxy object
return {
getValue: function() {
return [SOME OTHER VALUE I CHOOSE, internal.getValue()[1]];
}
}
}
// overwrite the original function with our decorated version
foo = decorator;
You can't access a variable in a closure. However, you can define the new function to delegate to the original function to access it:
var myFoo = new foo();
myFoo.getValue = (function (original) {
return function(){
var val = original();
val[0] = 0;
return val;
};
}(myFoo.getValue));
Here is a fiddle of this solution so you can try it out yourself: http://jsfiddle.net/6Ux92/1/
You can do like this
function myFoo() {
var vals = foo().getValue();
return {
getValue : function(){
return [0, vals[1]]
}
}
}
vals[1] is obviously myOtherValue
you could wrap this function with a decorator function:
var decorator = function() {
var someNewValue = ...;
var myOtherValue = foo().getValue()[1];
return [someNewValue, myOtherValue];
}
Try this :
function foo(){
this.myValue = 5;
var myOtherValue = 1;
return {
getValue: function(){
return [this.myValue, myOtherValue];
}
}
}
var bar = new foo();
bar.myValue = "whatever";

Javascript and module pattern

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.

Categories

Resources