With this code:
function printStuff(thing1, thing2) {
console.log(thing1 + ', ' + thing2);
};
function callWith() {
theFunc = arguments[0];
theArgs = [].slice.call(arguments, 1);
return function() {
theFunc.apply(this, theArgs);
};
};
x = callWith(printStuff, "apples", "cheese");
y = callWith(printStuff, "monkeys", "bananas");
x();
y();
...why is it that x and y seem to hold the same function? How do I get the desired behavior (i.e., store two different functions which always run printStuff with the parameters they were given when created)?
You need to create a different NEW instant of the printStuff method like this --
function printStuff(thing1, thing2) {
console.log(thing1 + ', ' + thing2);
};
function callWith() {
theFunc = arguments[0];
theArgs = [].slice.call(arguments, 1);
return new function() { // RETURN A NEW INSTANCE SO THAT IT HAS ITS OWN ARGUMENTS
theFunc.apply(this, theArgs);
};
};
x = callWith(printStuff, "apples", "cheese");
y = callWith(printStuff, "monkeys", "bananas");
x();
y();
Related
I'm troubleshooting some 3rd party code on a client's website. The client was having issues with the code not working. I found that the issue was related to bound JS functions. Arguments that were passed to the bound function were undefined. I couldn't figure out why. Everything seems fine. However, I then found that the client has overridden the Bind function. Here is what they have:
Function.prototype.bind = function(scope) {
var _function = this;
return function() {
return _function.apply(scope, arguments);
};
};
So if I create a function
var sumFunction = function(a, b){
console.log("a: " + a);
console.log("b: " + b);
return a + b;
}
Then bind that function:
var boundFunction = sumFunction.bind(null, 10);
When I call that bound function I get the following:
console.log(boundFunction(20));
a: 20
b: undefined
NaN
I found a similar SO question that was using the same bind function. javascript custom scope binding function
It appears that it used to work? The SO question I linked seemed to work back in 2013, but now it doesn't form me.
Is this just outdated? JavaScript isn't my main strength, but my client will want to know why their function is causing the problem.
I found the overridden bind function to be odd. Especially the line return _function.apply(scope, arguments); It seems like passing the entire arguments object is incorrect. Shouldn't it only send the arguments in array position 1 and higher? I tried changing that to this to test:
Function.prototype.bind = function(scope) {
var _function = this;
var newArgs = Array.prototype.slice.call(arguments, 1)
return function() {
return _function.apply(scope, newArgs );
};
};
But now I just get the following:
console.log(boundFunction(20));
a: 10
b: undefined
NaN
When the function is bounded, there might be an array of arguments after the 1st, so use slice(1) to get them. When the function is called, get the all the arguments, and concat both args arrays.
Concat both arrays of arguments:
Function.prototype.bind = function(scope) {
var _function = this;
var args1 = Array.prototype.slice.call(arguments, 1);
return function() {
var args2 = Array.prototype.slice.call(arguments, 0);
return _function.apply(scope, args1.concat(args2));
};
};
var sumFunction = function(a, b){
console.log("a: " + a);
console.log("b: " + b);
return a + b;
}
var boundFunction = sumFunction.bind(null, 10);
console.log(boundFunction(20));
However, calling slice on arguments, might cause the V8 engine to skip optimisation on the function. A better way would be to just iterate the arguments manually, and add them to a single array:
Function.prototype.bind = function(scope) {
var args = [];
var _function = this;
for(var i = 1; i < arguments.length; i++) { args.push(arguments[i]); }
return function() {
var newArgs = args.slice(0);
for(var i = 0; i < arguments.length; i++) { newArgs.push(arguments[i]); }
return _function.apply(scope, newArgs);
};
};
var sumFunction = function(a, b){
console.log("a: " + a);
console.log("b: " + b);
return a + b;
}
var boundFunction = sumFunction.bind(null, 10);
console.log(boundFunction(20));
I come across singleton pattern, it's quite tricky to understand how to implement it, and I know some people would suggest to avoid it most of the time, so below is specific singleton variation that I find it easy to understand, but somehow I feel that this is not the best implementation of this pattern, can you guys suggest better form of this pattern.
var Foo = (function () {
var instance;
var _priVar = 2;
var log = function() {
console.log("Hello");
};
function Singleton(x, y) {
if (instance) {
return instance;
}
this.name = x;
this.age = y + _priVar;
this.log = log;
instance = this;
}
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
and my goal is that when we do following
var a = new Foo("Bob", 24);
var b = new Foo();
var c = Foo();
var d = Foo.getInstance();
we will still get
a == b // true
a == c // true
a == d // true
a.name // 'Bob'
b.age // 26
c.log // 'Hello'
d.name // 'Bob'
The simplest singleton, also known as module pattern, consists of an object literal:
var foo = (function () {
var x = "Bob",
y = 24,
_priVar = 2;
function log() {
console.log("Hello");
}
return {
name: x,
age: y + _priVar,
log: log
};
}());
If you want to introduce lazy initialisation, you can use an extra getInstance function like in your implementation:
var getFoo = (function () {
var instance = null;
return function getFooInstance() {
if (instance) return instance;
var x = "Bob",
y = 24,
_priVar = 2;
function log() {
console.log("Hello");
}
return instance = {
name: x,
age: y + _priVar,
log: log
};
};
}());
A singleton should never use a constructor like in your code, that's just unnecessary. If you feel a need to pass arguments for initialisation, don't make it a singleton.
I am reading a book which contains the following example:
var composition1 = function(f, g) {
return function(x) {
return f(g(x));
}
};
Then the author writes: "...naive implementation of composition, because it does not take the execution context into account..."
So the preferred function is that one:
var composition2 = function(f, g) {
return function() {
return f.call(this, g.apply(this, arguments));
}
};
Followed by an entire example:
var composition2 = function composition2(f, g) {
return function() {
return f.call(this, g.apply(this, arguments));
}
};
var addFour = function addFour(x) {
return x + 4;
};
var timesSeven = function timesSeven(x) {
return x * 7;
};
var addFourtimesSeven2 = composition2(timesSeven, addFour);
var result2 = addFourtimesSeven2(2);
console.log(result2);
Could someone please explain to me why the composition2 function is the preferred one (maybe with an example)?
EDIT:
In the meantime i have tried to use methods as arguments as suggested, but it did not work. The result was NaN:
var composition1 = function composition1(f, g) {
return function(x) {
return f(g(x));
};
};
var composition2 = function composition2(f, g) {
return function() {
return f.call(this, g.apply(this, arguments));
}
};
var addFour = {
myMethod: function addFour(x) {
return x + this.number;
},
number: 4
};
var timesSeven = {
myMethod: function timesSeven(x) {
return x * this.number;
},
number: 7
};
var addFourtimesSeven1 = composition1(timesSeven.myMethod, addFour.myMethod);
var result1 = addFourtimesSeven1(2);
console.log(result1);
var addFourtimesSeven2 = composition2(timesSeven.myMethod, addFour.myMethod);
var result2 = addFourtimesSeven2(2);
console.log(result2);
This just answers what composition2 actually does:
composition2 is used when you want to keep this as context in the functions itself. The following example shows that the result is 60 by using data.a and data.b:
'use strict';
var multiply = function(value) {
return value * this.a;
}
var add = function(value) {
return value + this.b;
}
var data = {
a: 10,
b: 4,
func: composition2(multiply, add)
};
var result = data.func(2);
// uses 'data' as 'this' inside the 'add' and 'multiply' functions
// (2 + 4) * 10 = 60
But yet, it still breaks the following example (unfortunately):
'use strict';
function Foo() {
this.a = 10;
this.b = 4;
}
Foo.prototype.multiply = function(value) {
return value * this.a;
};
Foo.prototype.add = function(value) {
return value + this.b;
};
var foo = new Foo();
var func = composition2(foo.multiply, foo.add);
var result = func(2); // Uncaught TypeError: Cannot read property 'b' of undefined
Because the context of composition2 (this) is undefined (and is not called in any other way, such as .apply, .call or obj.func()), you'd end up with this being undefined in the functions as well.
On the other hand, we can give it another context by using the following code:
'use strict';
var foo = new Foo();
var data = {
a: 20,
b: 8,
func: composition2(foo.multiply, foo.add)
}
var result = data.func(2);
// uses 'data' as 'this'
// (2 + 8) * 10 = 200 :)
Or by explicitly setting the context:
'use strict';
var multiply = function(value) {
return value * this.a;
};
var add = function(value) {
return value + this.b;
};
var a = 20;
var b = 8;
var func = composition2(multiply, add);
// All the same
var result1 = this.func(2);
var result2 = func.call(this, 2);
var result3 = func.apply(this, [2]);
composition1 would not pass arguments other than the first to g()
If you do:
var composition1 = function(f, g) {
return function(x1, x2, x3) {
return f(g(x1, x2, x3));
}
};
the function will work for the first three arguments. If you however want it to work for an arbitrary number, you need to use Function.prototype.apply.
f.call(...) is used to set this as shown in Caramiriel's answer.
I disagree with the author.
Think of the use-case for function-composition. Most of the time I utilize function-composition for transformer-functions (pure functions; argument(s) in, result out and this is irrelevant).
2nd. Utilizing arguments the way he does it leads into a bad practice/dead end, because it implies that the function g() might depend on multiple arguments.
That means, that the composition I create is not composable anymore, because it might not get all arguments it needs.
composition that prevents composition; fail
(And as a side-effect: passing the arguments-object to any other function is a performance no-go, because the JS-engine can't optimize this anymore)
Take a look at the topic of partial application, usually misreferenced as currying in JS, wich is basically: unless all arguments are passed, the function returns another function that takes the remaining args; until I have all my arguments I need to process them.
Then you should rethink the way you implement argument-order, because this works best when you define them as configs-first, data-last.Example:
//a transformer: value in, lowercased string out
var toLowerCase = function(str){
return String(str).toLowerCase();
}
//the original function expects 3 arguments,
//two configs and the data to process.
var replace = curry(function(needle, heystack, str){
return String(str).replace(needle, heystack);
});
//now I pass a partially applied function to map() that only
//needs the data to process; this is really composable
arr.map( replace(/\s[A-Z]/g, toLowerCase) );
//or I create another utility by only applying the first argument
var replaceWhitespaceWith = replace(/\s+/g);
//and pass the remaining configs later
arr.map( replaceWhitespaceWith("-") );
A slightly different approach is to create functions that are, by design, not intended to get all arguments passed in one step, but one by one (or in meaningful groups)
var prepend = a => b => String(a) + String(b); //one by one
var substr = (from, to) => value => String(str).substr(from, to); //or grouped
arr.map( compose( prepend("foo"), substr(0, 5) ) );
arr.map( compose( prepend("bar"), substr(5) ) );
//and the `to`-argument is undefined; by intent
I don't intend to ever call such functions with all the arguments, all I want to pass them is their configs, and to get a function that does the job on the passed data/value.
Instead of substr(0, 5, someString), I would always write someString.substr(0, 5), so why take any efforts to make the last argument (data) applyable in the first call?
Or, in other words, how to make this work:
function foo(){}
//do something that modifies foo as if it was defined with "function foo(a,b,c){};"
console.log(foo.length);
//output: 3
It is possible, but maybe not very nice:
function lengthDecorator(fun) {
function update(len) {
var args = []; // array of parameter names
for (var i = 0; i < len; ++i) {
args.push('a' + i);
}
var result = new Function('fun',
'return function(' + args.join(',') + ') {' +
'var args = Array.prototype.slice.call(arguments);' +
'return fun.apply(this, args);' + // call supplied function
'}'
); // create a function that will return a function
result = result(fun); // make the fun param known to the inner function
result.update = update;
return result;
}
return update(fun.length);
}
Example usage:
var foo = lengthDecorator(function(a,b) {
return a+b;
});
print('foo.length: ' + foo.length);
print('foo(2, 3): ' + foo(2, 3));
print('');
foo = foo.update(42);
print('foo.length: ' + foo.length);
print('foo(2, 3): ' + foo(2, 3));
Output:
foo.length: 2
foo(2, 3): 5
foo.length: 42
foo(2, 3): 5
(Live demo: Ideone.com, jsFiddle)
lengthDecorator wraps the supplied function with a function that takes the same amount of parameters as the supplied function. The parameter count can be changed with update.
C.f.
new Function(...): Dynamically create a new function.
fun.apply(...): "Calls a function with a given this value and arguments provided as an array."
function foo() {}
alert(foo.length); // 0
foo = function (a, b, c) {}
alert(foo.length); // 3
I'm not sure what you're actually trying to do, but you can store the old foo in var and then redefine foo.
function foo() {...}
var oldfoo = foo;
foo = function (a, b, c) {
oldfoo();
}
But what's the point?
The length property of a function object is non-writable and non-configurable, so there is no way to change its value.
You could define a new function which invokes the original function internally...
Consider this:
function f2(x) {
return x+1;
};
X = function(){
this.f1=function (x) {
return 2*f2(x);
}
return this;
};
then x = new X(); x.f1(1) works fine.
But when i want to do this:
X = function(){
this.f2 = function(x) {
return x+1;
};
this.f1=function (x) {
return 2*f2(x);
}
return this;
};
The same statement will complain that it can't find f2.
In, for example c#, you can say
class X {
int f2(int x){return x+1;}
int f1(int x){return 2*f2(x);}
}
and this will work
X x=new X();
x.f1(1)
Why?
You need to reference the f2 with the this keyword explicitly.
X = function(){
this.f2 = function(x) {
return x+1;
};
this.f1=function (x) {
return 2*this.f2(x);
}
return this;
};
because you forgot this.f2. Javascript don't see class variables without this
To reference f2 in your second code block, you'll need to use this.f2. this references the context in which the function is being executed. Since you call f1 in the following way:
x.f1();
... the context is set to the instance, x.
JavaScript does not make instance variables available to the scope in the same way as scope variables, i.e. those directly available:
X = function(){
var f2 = 123;
this.f2 = function(x) {
return x+1;
};
this.f1=function (x) {
console.log(f2); // => 123
console.log(this.f2); // => function(){}
return 2 * this.f2(x);
};
return this;
};
Javascript doesn't have the implicit this that you get in C#. You need to add the this in:
X = function(){
this.f2 = function(x) {
return x+1;
};
this.f1=function (x) {
return 2*this.f2(x);
};
return this;
};
X = function(){
this.f2 = function(x) {
return x+1;
};
this.f1=function (x) {
return 2*this.f2(x); // <-- Need this here since it is not implicit
}
return this;
};