Given this code:
var arr = ['one', 'two'];
var obj = {
func: function(a, b) {
console.log(a, b);
}
};
Is there a way to dynamically construct the function call passing the items in the array as arguments without using eval()? Basically, the equivalent of this:
eval('obj.func(' + arr.join(',') + ')');
You can spread the array into the argument list:
var arr = ['one', 'two'];
var obj = {
func: function(a, b) {
console.log(a, b);
}
};
obj.func(...arr);
Or, if the environment doesn't support spread, you can use apply, which allows you to call a function with the supplied array converted to parameters:
var arr = ['one', 'two'];
var obj = {
func: function(a, b) {
console.log(a, b);
}
};
obj.func.apply(undefined, arr);
Related
var add = function(a, b) {
return a + b;
}
var addOne =add.bind(null,1);
var result = addOne(4);
console.log(result);
Here the binded value of a is 1 and b is 4.
How to assign the binding value i.e)1 to the second argument of the function without using spread operator(...)
You could take a swap function with binding the final function.
var add = function (a, b) { console.log(a, b); return a + b; },
swap = function (a, b) { return this(b, a); },
addOne = swap.bind(add, 1),
result = addOne(4);
console.log(result);
With decorator, as georg suggested.
var add = function (a, b) { console.log(a, b); return a + b; },
swap = function (f) { return function (b, a) { return f.call(this, a, b) }; },
addOne = swap(add).bind(null, 1),
result = addOne(4);
console.log(result);
You could use the arguments object for reordering the parameters.
var add = function (a, b, c, d, e) {
console.log(a, b, c, d, e);
return a + b + c + d + e;
},
swap = function (f) {
return function () {
var arg = Array.apply(null, arguments);
return f.apply(this, [arg.pop()].concat(arg));
};
},
four = swap(add).bind(null, 2, 3, 4, 5),
result = four(1);
console.log(result);
You can use the following way
var add = function(x){
return function(y){
return x+y;
}
}
add(2)(3); // gives 5
var add5 = add(5);
add5(10); // gives 15
here add5() would set x = 5 for the function
This will help you what you need
var add = function(a) {
return function(b) {
return a + b;
};
}
var addOne = add(1);
var result = addOne(4);
console.log(result);
You can try this
function add (n) {
var func = function (x) {
if(typeof x==="undefined"){
x=0;
}
return add (n + x);
};
func.valueOf = func.toString = function () {
return n;
};
return func;
}
console.log(+add(1)(2));
console.log(+add(1)(2)(3));
console.log(+add(1)(2)(5)(8));
I have been working on cartesian product for single elements and array of objects. For single array elements I have understood the solution but for array of objects I struggle to achieve.
For example input
cartesianProductOf([{col1:'A'}], [{col2:'B'},{col3:'C'}])
Output :
[{col1:'A',col2:'B'},{col1:'A',col3:'C'}]
Here is the function which I was working on
function cartesianProductOf() {
return Array.prototype.reduce.call(arguments, function(a, b) {
var ret = [];
debugger;
a.forEach(function(a) {
b.forEach(function(b) {
var r = a.concat([b])
ret.push(r);
});
});
return ret;
}, [[]]);
}
This function returning this result
[{col1:'A'},{col2:'B'}],[{col1:'A'},{col3:'C'}]
Need guidance.
Instead of using an array to push to, you want to merge the objects:
function cartesianProductOf() {
return Array.prototype.reduce.call(arguments, function(a, b) {
var ret = [];
a.forEach(function(a_el) {
b.forEach(function(b_el) {
ret.push(Object.assign({}, a_el, b_el));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
});
});
return ret;
}, [{}]);
// ^^
}
If you don't want to use Object.assign or it's polyfill, the equivalent would be
var r = {};
for (var p in a_el)
r[p] = a_el[p];
for (var p in b_el)
r[p] = b_el[p];
ret.push(r);
Here's a solution using Ramda.js
const cartesianProduct = (...Xs) =>
R.reduce(
(Ys, X) =>
R.map(R.apply(R.append), R.xprod(X, Ys)),
[[]],
Xs
)
const cartesianProductOf = (...objs) =>
R.map(R.mergeAll, cartesianProduct(...objs))
console.log(
cartesianProductOf(
[{col1: 'A'}],[{col2: 'B'}, {col3: 'C'}],
)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
I am new to JS, and I have read a code that contains this line.
this.myArray[index](this._sender, args);
I wonder what it means?
It means that this array item is a function, and it is being called with arguments this._sender and args.
In this example, I declare an array, push a single-argument function to it, and call it.
var arr = [];
arr.push(function(str) {
document.body.innerHTML = "Hey, " + str;
});
arr[0]("Your name");
that means that the myArray[index] is the element of myArray that is function that is why it requires 2 arguments.
It is similar to following snippet:
var myClass = function () {
this._a = 5;
var index = arguments[0] || 0;
this.myArray = [
function (a, b) {
console.log(a, b);
},
function (a, b) {
console.log(a, b);
}
];
this.myArray[index](this._a, arguments);
};
var obj = new myClass(1, 2, 3);//5 [1, 2, 3]
In JavaScript, functions are first class objects so they can be passed around/referenced, stored, and accessed like any other value.
var myArray = [];
var myFunction = function(name) {
console.log("Hello, " + name + "!");
};
myFunction('World');
myArray[0] = myFunction;
myArray[0]('again');
function addDefault(func, defaultValue) {
return function(name) {
name = name ? name : defaultValue;
func(name);
}
}
var myFunctionWithDefault = addDefault(myFunction, 'stranger');
myFunctionWithDefault();
myFunctionWithDefault('goodbye');
JSBin: http://jsbin.com/wubuye/edit?js,console
How to merge these two arrays using JavaScript:
[{"id1":"value1","id2":"value2"}]
[{"id3":"value3","id4":"value4"}]
Into this:
[{"id1":"value1","id2":"value2","id3":"value3","id4":"value4"}]
You can use a simple function.
Either by adding the key/values from b into a:
function merge(a, b) {
for (var p in b[0]) {
a[0][p] = b[0][p];
}
return a;
}
merge(a, b);
Or by using a native array function like reduce:
function merge2(a, b) {
return b.reduce(function (el) {
return el;
}, a);
}
console.log(merge2(a, b));
DEMO
Just use the built-in Javascript Array .concat() method.
http://www.w3schools.com/jsref/jsref_concat_array.asp
var a = ["id1","value1","id2","value2"]
var b = ["id3","value3","id4","value4"]
var c = a.concat(b)
//c is now ["id1","value1","id2","value2","id3","value3","id4","value4"]
B = function(fn) {
var ex_array = ['a', 'b'];
this.b_fn = function () {
fn.apply(what_should_be_there, ex_array);
}
}
A = function() {
this.a_fn = function (a, b) {
//do sth
}
var b = new B(fn);
}
Only what I would like to do is use apply with on function fn in object b, but with "old" context, I mean in this case with context of object of class A
Here's a solution where a_fn isn't prebound to an arguments array. I added some logging as demo:
var B = function(fn) {
var ex_array = [ 'a', 'b' ];
this.b_fn = function () {
fn(ex_array);
};
};
var A = function() {
this.c = 'hello world';
this.a_fn = function(a, b) {
console.log('a:', a);
console.log('b:', b);
console.log('c:', this.c);
};
var b = new B(Function.prototype.apply.bind(this.a_fn, this));
b.b_fn();
};
Edit
If you want to use ex_array as an array of arguments so that apply will iterate through them, do this (jsfiddle):
B = function(fn) {
var ex_array = ['a', 'b'];
this.b_fn = function() {
return fn.apply(null, ex_array);
};
}
A = function() {
this.a_fn = function (a, b) {
console.log(this, a, b);
}
var b = new B(this.a_fn.bind(this));
b.b_fn(); // => A {}, "a", "b"
}
new A();
Previous answer
See this working demo on jsfiddle:
B = function(fn) {
var ex_array = ['a', 'b'];
this.b_fn = fn.bind(null, ex_array);
}
A = function() {
this.a_fn = function (a, b) {
console.log(this, a);
}
var b = new B(this.a_fn.bind(this));
b.b_fn(); // => A {}, ['a', 'b'];
}
new A();
Basically, all you need to do is bind this.a_fn with its current context. The trick is to use .bind(null, /* args */) when making it this.b_fn, so it keeps the original A context, but allows you to pass in another parameter (in this case, ['a', 'b'].