Generic function? - javascript

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?';

Related

Difficulties with using function expression

Hopefully you will answer it !
var myform = document.getElementById("myform"),
saveBtn = document.getElementById("submit");
saveBtn.addEventListener("click", saveInfo);
var saveInfo = function (e){
e.preventDefault();
var dateValue = document.getElementById("inputdeadline").value;
var todoValue = document.getElementById("textarea").value;
todoValue = todoValue.replace(/\n/g," ");
if ( dateValue > 24 || dateValue <= 0) {
myform.reset();
return false;
};
if (!(todoValue)) {
myform.reset();
return false;
};
var todoObj = {
todoValue,
dateValue
};
if (localStorage.getItem("localTodoItem") === null) {
var todoArray = [];
todoArray.push(todoObj);
todoArray.sort(function (a, b) {
return a.dateValue - b.dateValue;
});
localStorage.setItem("localTodoItem", JSON.stringify(todoArray));
} else {
var todoArray = JSON.parse(localStorage.getItem("localTodoItem"));
todoArray.push(todoObj);
todoArray.sort(function (a, b) {
return a.dateValue - b.dateValue;
});
localStorage.setItem("localTodoItem", JSON.stringify(todoArray));
};
showTodoItems();
myform.reset();
};
Here when I am using function declaration for this saveInfo function it is correctly doing all functionalities but when I am using function expression it just reload the page that's it nothing happening.
Please help me.
If you need more clarification about code please visit github.
This is because function declarations are hoisted, whereas function expressions are not. You're using saveInfo before the expression is executed, which would work for a declaration but not an expression.
Function declaration hoisting on MDN

Javascript function does not return the right value

So i have this code:
function Class1() {
this.i = 1;
var that=this;
function nn() {
return 21;
}
this.aa = function() {
nn();
};
this.bb = function() {
this.aa();
};
this.cc = function() {
this.bb();
};
}
var o = new Class1();
var b=o.cc();
alert(b); //undefined
But when the alert is fired, I get an undefined error and not 21, Does the private method can not use a return? Thanks!
When using the function() {} syntax to define a function, you always explicitly need to return the value, i.e. not only from nn, but from all intermediate functions as well.
function Class1() {
this.i = 1;
var that = this;
function nn() {
return 21;
}
this.aa = function() {
return nn();
}
this.bb = function() {
return this.aa();
}
this.cc = function() {
return this.bb();
}
}
var o = new Class1();
var b = o.cc();
alert(b); // "21"
Apart from the answer above, the 'this' context seems weird in your functions. Maybe you are better of with arrow functions if you dont want to bind the this context to each function. I also think that it is better to actually separate private and public functions when using a 'class' like this.
function Class1() {
var _nn = function () {
return 21;
}
var _aa = function () {
return _nn();
}
var _bb = function () {
return _aa();
}
var cc = function () {
return _bb();
};
return {
cc
};
}
var o = new Class1();
var a = o.cc();
console.log(a);
Much easier to understand that it is only cc that is a public function.
So with arrow function it would instead look like this, and you can use the Class1 this context inside of your private functions without doing
var that = this; or using bind.
function Class1() {
this.privateThing = 'private';
var _nn = () => { return this.privateThing; };
var _aa = () => { return _nn(); };
var _bb = () => { return _aa(); };
var cc = () => { return _bb(); };
return {
cc
};
}

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

Writing a function to set some but not necessarily all parameters in another function

I had a coding interview test that asked the following question which I was not able to fully solve. I'm wondering the best way to do this following my approach -- also sorry this is long.
You are given a function to read in like this (not necessarily 2 parameters):
function add(a, b) {
return a + b;
}
The objective is to create a function to initialize some of those variables and again call the function to perform the calculation like, function setParam(func, params). To use this you would do the following:
_add = setParam(add, {b:9})
_add(10) // should return 19
My solution was to parse the function to see how many parameters there are, then set them using the given parameters but since I barely know javascript I was never able to actually return a function with only some variables set and others still undefined.
(attempt at solution)
function setParam(func, params) {
// varray is an array of the the varriables from the function, func
// ie varray = [a,b] in this test
var varray = /function[^\(]*\(([^\)]*)\)/.exec(func.toString())[1].split(',');
//creates an array, paramset, that has the variables in func defined
//where possible
// ex paramset = [a,9] if only b was set
var paramsset = []
for (i = 0; i < varray.length; i++) {
if (typeof(params[varray[i]]) == "undefined"){
paramsset[i] = varray[i];
} else {
paramsset[i] = params[varray[i]];
}
}
//////
// need to modify existing function and return with added parameters
// where I'm stuck as this doesn't work.
newfunc = (function(){
var _func = func;
return function() {
return _func.apply(this, paramsset);
}
})();
newfunc()
}
I'm sure I'm not doing this the correct way, but any help would be appreciated.
I'm certainly not advocating to go towards that solution, but I still implemented something to follow your initial's API design for fun. The signatures weak map is necessary in order to preserve the initial function's signature so that we can call setParams again on partially applied functions.
var setParams = (function () {
var signatures = new WeakMap();
return function (fn, paramsToApply) {
var signature = signatureOf(fn), newFn;
validateParams(paramsToApply, signature.params);
newFn = function () {
var params = appliedParamsFrom(arguments, paramsToApply, signature.indexes);
return fn.apply(this, params);
};
signatures.set(newFn, signature);
return newFn;
};
function signatureOf(fn) {
return signatures.has(fn)?
signatures.get(fn) :
parseSignatureOf(fn);
}
function parseSignatureOf(fn) {
return String(fn)
.match(/function.*?\((.*?)\)/)[1]
.replace(/\s+/g, '')
.split(',')
.reduce(function (r, param, index) {
r.indexes[param] = index;
r.params.push(param);
return r;
}, { indexes: {}, params: [] });
}
function validateParams(paramsToApply, actualParams) {
Object.keys(paramsToApply).forEach(function (param) {
if (actualParams.indexOf(param) == -1) throw new Error("parameter '" + param + "' could not be found in the function's signature which is: 'function (" + actualParams + ")'");
});
}
function appliedParamsFrom(args, paramsToApply, paramsIndex) {
var appliedParams = [],
usedIndexes = [],
argsIndex = 0,
argsLen = args.length,
argSpotIndex = 0;
Object.keys(paramsToApply).forEach(function (param) {
var index = paramsIndex[param];
appliedParams[index] = paramsToApply[param];
usedIndexes.push(index);
});
while (argsIndex < argsLen) {
if (usedIndexes.indexOf(argSpotIndex) == -1) {
appliedParams[argSpotIndex] = args[argsIndex++];
}
++argSpotIndex;
}
return appliedParams;
}
})();
function add(a, b) { return a + b; }
var addTo9 = setParams(add, { b: 9 });
var add10To9 = setParams(addTo9, { a: 10 });
document.write(addTo9(10) + ', ' + add10To9());
Now, note that JavaScript comes with the Function.prototype.bind function which allows to perform in-order partial function application. The first parameter to bind has nothing to do with arguments, it's to bind the this value.
function add(a, b) { return a + b; }
var addTo9 = add.bind(null, 9);
document.write(addTo9(10));
And finally, an implementation with a placholder if you need one:
var partial = (function (undefined) {
var PLACEHOLDER = {};
function partial(fn, partialArgs) {
return function () {
return fn.apply(this, applyPartialArgs(arguments, partialArgs));
};
}
Object.defineProperty(partial, 'PLACEHOLDER', {
get: function () { return PLACEHOLDER; }
});
return partial;
function applyPartialArgs(args, partialArgs) {
var appliedArgs = partialArgs.map(function (arg) {
return arg === PLACEHOLDER? undefined : arg;
}),
partialArgsLen = partialArgs.length,
argsLen = args.length,
argsIndex = 0,
argSpotIndex = 0;
while (argsIndex < argsLen) {
if (
partialArgs[argSpotIndex] === PLACEHOLDER ||
argSpotIndex >= partialArgsLen
) {
appliedArgs[argSpotIndex] = args[argsIndex++];
}
++argSpotIndex;
}
return appliedArgs;
}
})();
function add(a, b, c, d) {
return a + b + c + d;
}
var _ = partial.PLACEHOLDER;
var addTo9 = partial(add, [_, 5, _, 4]);
document.write(addTo9(5, 5));
I'm guessing that they might have been testing for knowledge of partial application. (not currying)
Edit: Edited based upon your comments. This is Crockford's curry function straight from his book.
function add(a, b) {
return a + b;
}
if (!Function.prototype.partial) {
Function.prototype.partial = function() {
var slice = Array.prototype.slice,
args = new Array(arguments.length),
that = this;
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
return function() {
return that.apply(null, args.concat(slice.apply(arguments)));
}
};
}
var example = add.partial(4);
console.log(example(10)); // output 14
console.log(example(20)); // output 24
var example = adder(4) assigns example to be function with a closure with a (in this case 4). When example is called like in the console.log, it will in effect be returning "the value of a when example was assigned, plus this new number."
Walkthrough of the partial() function:
Converts arguments to an array
returns a function gets passed the arguments given, which can be called later. It has a closure with the previously assigned arguments.

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