I am a bit confused as which one of the following is the right way to create a handler containing functions...An object with function or a new function itself?
Say, a handler for calculator functions...
CalculatorHandler = new function(){
this.add = new function(a, b){
return a + b;
};
this.sub = new function(a, b){
return a-b;
};
};
Or
CalculatorHandler = {
this.add: function(a, b){
return a + b;
},
this.sub: function(a, b){
return a-b;
}
};
Are there any advantage/disadvantage of one over the other?
If you just want to have a "basket" to hold your functions together, simply use an object, there is no need for a constructor function:
CalculatorHandler = {
add: function(a, b){
return a + b;
},
sub: function(a, b){
return a-b;
}
};
Note how the this in your example is incorrect as it will refer to the scope you define the CalculatorHandler object in (probably global - window).
On the other hand if you want to build a calculator to have some data and do operations on it, then you can use the OOP-like approach in your first example.
CalculatorHandler = function() {
this.total=0;
this.add = function(a) {
this.total += a;
};
this.sub = function(a) {
this.total -= a;
};
}
var calc = new CalculatorHandler();
calc.add(4);
calc.sub(3);
And a better solution, based on prototipal inheritance:
CalculatorHandler = function() {
this.total=0;
}
CalculatorHandler.prototype.add = function(num) {
this.total += num;
}
CalculatorHandler.prototype.sub = function(num) {
this.total -= num;
};
var calc = new CalculatorHandler();
calc.add(4);
calc.sub(3);
Related
i've been having a lot of trouble understand how this currying function actually works
and what exactly its doing ?
Function.prototype.curry = function() {
var fn = this, args = Array.prototype.slice.call(arguments);
return function() {
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments)));
};
};
because im only familiar with this type of currying function:
function curry(f) {
return function(a) {
return function(b) {
return f(a, b);
};
}
var modularpattern = (function () {
var sum = 0;
return {
add: function () {
sum = sum + 1;
return sum;
},
}
} ());
var c = modularpattern;
c.add(); // 1
var d = modularpattern;
d.add(); // 2 but I want to be 1
console.log(modularpattern.add()); // alerts: 3
Is it possible to have more objects not only one? I want to have private fields but at the same time also having more that just one object?
Yes, that's easily possible by dropping the IIFE invocation to get a normal function instead. Only it's called factory pattern then, no longer module.
function factory() {
var sum = 0;
return {
add: function () {
sum = sum + 1;
return sum;
}
}
}
var c = factory();
c.add(); // 1
var d = factory();
d.add(); // 1
console.log(c.add()); // logs: 2
You can use the module pattern to create a factory which uses the module pattern to create more objects. Using your original example, it would look something like this:
var moduleFactory = (function() {
return {
create: function() {
return (function() {
var sum = 0;
return {
add: function() {
sum = sum + 1;
return sum;
}
}
})();
}
}
}
)();
var c = moduleFactory.create();
console.log(c.add()); //1
var d = moduleFactory.create();
console.log(d.add()); //1
I'm learning Javascript and wondering if it's possible to store a declared function in a variable to be used later?
For context,
function add(a, b) {
return a + b;
}
var addTogether = _.partial(add, 1);
doSomething() // returns a promise that resolves to a 2
.then(addTogether); // expect to return 3
Is there a way to achieve this?
var Add = function (a, b)
{
return a + b;
}
var result = Add (2, 3);
Absolutely. Functions ARE data in JavaScript.
var foo = function(a, b) {
return a + b;
}
Is perfectly legitimate.
function add(a, b) {
return a + b;
}
var foo = add;
console.log(foo(5,10));
console.log(add(10, 20));
You can also use ES6 syntax to store anonymous functions in constants, like so:
const add = (a, b) => a + b;
const addOne = a => add(a, 1);
console.log(add(5, 10)); // 15
console.log(addOne(5)); // 6
var myString = '';
myString += 'foo';
myString += 'bar';
myString = myString.replace(/oba/, 'qux');
console.log(myString) // produces "foquxr"
Is there any way to likewise tinker around with functions, like, say, turning function(a) { a += 'b'; return a; } info function(a) { a += 'b'; console.log(a); return a + 'c'; }?
You can compose functions thus
// (compose(f, g))(x, y, ...) is the same as f(g(x, y, ...))
function compose(f, g) {
return function (var_args) {
return f.call(this, g.apply(this, arguments));
};
}
so
var f = compose(
function (x) { console.log(x); return x + 'c'; },
function (a) { a += 'b'; return a; });
lets you combine two small functions to get a function that behaves like
function(a) { a += 'b'; console.log(a); return a + 'c'; }
You could achieve this (without using eval) by getting the function's body from its declaration, manipulating it as needed, and redefining it by means of the Function() constructor:
function myFunction(a) { a += 'b'; return a; }
function changeFunction(){
var func = window['myFunction'].toString();
var body = func.substring(func.indexOf("{")+1, func.lastIndexOf("}"));
body = body.replace("return a;", "console.log(a); return a + 'c';");
window.myFunction = Function("a", body);
}
Here's a JSFiddle
Let's say I have a JavaScript object:
function a(){
var A = [];
this.length = function(){
return A.length;
};
this.add = function(x){
A.push(x);
};
this.remove = function(){
return A.pop();
};
};
I can use it like so:
var x = new a();
x.add(3);
x.add(4);
alert(x.length()); // 2
alert(x.remove()); // 4
alert(x.length()); // 1
I was trying to make .length not a function, so I could access it like this: x.length, but I've had no luck in getting this to work.
I tried this, but it outputs 0, because that's the length of A at the time:
function a(){
var A = [];
this.length = A.length;
//rest of the function...
};
I also tried this, and it also outputs 0:
function a(){
var A = [];
this.length = function(){
return A.length;
}();
//rest of the function...
};
How do I get x.length to output the correct length of the array inside in the object?
You could use the valueOf hack:
this.length = {
'valueOf': function (){
return A.length;
},
'toString': function (){
return A.length;
}
};
Now you can access the length as x.length. (Although, maybe it's just me, but to me, something about this method feels very roundabout, and it's easy enough to go with a sturdier solution and, for example, update the length property after every modification.)
If you want A to stay 'private', you need to update the public length property on every operation which modifies A's length so that you don't need a method which checks when asked. I would do so via 'private' method.
Code:
var a = function(){
var instance, A, updateLength;
instance = this;
A = [];
this.length = 0;
updateLength = function()
{
instance.length = A.length;
}
this.add = function(x){
A.push(x);
updateLength();
};
this.remove = function(){
var popped = A.pop();
updateLength();
return popped;
};
};
Demo:
http://jsfiddle.net/JAAulde/VT4bb/
Because when you call a.length, you're returning a function. In order to return the output you have to actually invoke the function, i.e.: a.length().
As an aside, if you don't want to have the length property be a function but the actual value, you will need to modify your object to return the property.
function a() {
var A = [];
this.length = 0;
this.add = function(x) {
A.push(x);
this.length = A.length;
};
this.remove = function() {
var removed = A.pop();
this.length = A.length;
return removed;
};
};
While what everyone has said is true about ES3, that length must be a function (otherwise it's value will remain static, unless you hack it to be otherwise), you can have what you want in ES5 (try this in chrome for example):
function a(){
var A = [],
newA = {
get length(){ return A.length;}
};
newA.add = function(x){
A.push(x);
};
newA.remove = function(){
return A.pop();
};
return newA;
}
var x = a();
x.add(3);
x.add(4);
alert(x.length); // 2
alert(x.remove()); // 4
alert(x.length); // 1
You should probably use Object.create instead of the function a, although I've left it as a function to look like your original.
I don't think you can access it as a variable as a variable to my knoledge cannot return the value of a method, unless you will hijack the array object and start hacking in an update of your variable when the push/pop methods are called (ugly!). In order to make your method version work I think you should do the following:
function a(){
this.A = [];
this.length = function(){
return this.A.length;
};
this.add = function(x){
this.A.push(x);
};
this.remove = function(){
return this.A.pop();
};
};
These days you can use defineProperty:
let x = {}
Object.defineProperty(x, 'length', {
get() {
return Object.keys(this).length
},
})
x.length // 0
x.foo = 'bar'
x.length // 1
Or in your specific case:
Object.defineProperty(x, 'length', {
get() {
return A.length
}
})
function a(){
this.A = [];
this.length = function(){
return this.A.length;
};
this.add = function(x){
this.A.push(x);
};
this.remove = function(){
return this.A.pop();
};
};