Use apply or call with "old" context - javascript

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'].

Related

Execute Multiple functions in a function

function executeActions(param)
{
if((param != undefined) && (param.length > 0))
{
for(i=0; i < param.length; i++)
{
//eval like function
param[i]();
}
}
}
function clearFields()
{
...
}
function showAbs(param)
{
if(param == 'insert')
{
...
}
else if(param == 'update')
{
...
}
else
{
...
}
}
$("#clearButton").click(function(event)
{
//var functions = ["clearFields()","showAbs('insert')"];
var a = showAbs('insert');
var functions = [clearFields, a];
executeActions(functions);
});
Hello everyone!
How can I execute some functions with parameters in a row in a set of instructions like i've showed above?
If they don't have any parameters, then the functions execute like in chain, but, if one or more of them uses
some parameters, it stops with the error: "param[i] is not a function".
Maybe if you have another elegant solution for this code, i'd appreciate if you share with us.
Thank you all in advance!
You can use partial application for this. Partial application means that you take a given function and fix one or more parameters to it. Example
function sum(a, b){
return a + b;
}
function product(a, b){
return a * b;
}
function doSomething(){
// do something
}
function runFunctions(funcs){
for(var i = 0;i<funcs.length;i++){
funcs[i]();
}
}
var mySum = function(){
return sum(5, 6);
}
var myProduct = function(){
return product(2, 3);
}
runFunctions(mySum, myProduct, doSomething);
The above is using ES 5 syntax. You could make this a bit more concise using ES 6 syntax:
const sum = (a, b) => a + b;
const product = (a, b) => a * b;
const doSomething = () => // do something
const runFunctions = funcs => {
for(func of funcs)
func();
}
var mySum = () => sum(5, 6);
var myProduct = () => product(2, 3);
runFunctions(mySum, myProduct, doSomething);
or you could use the bind function to take care of fixing the vars:
const sum = (a, b) => a + b;
const product = (a, b) => a * b;
const doSomething = () => // do something
const runFunctions = funcs => {
for(func of funcs)
func();
}
runFunctions(sum.bind(null, 5,6), myProduct.bind(null, 2,3), doSomething);
For me a way you want to achieve may be not readable for other developers.
You may create a function that will group all your function executions like:
function groupedFunctions{
return {
A: funcA(param),
B: funcB(param),
C: funcC(param)
}
}
function executeActions(funcObj, params) {
funcObj.A(params.a);
funcObj.B(params.b);
}
let params = {a: 1, b:2}
executeActions(groupedFunction(), params)

How to dynamically construct a function's arguments without eval?

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);

Bind only second argument to javascript function

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));

JavaScript : what does it mean to have brackets () after array[]?

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 supplement object function from outside

var object = {}; //lots of stuff in here
var func = object.dosome;
object.dosome = function(a,b) {
func(a,b);
//someth else here i need to add
}
This works but ugly.
So is there a way to supplement object.dosome method, without creating a new variable containing it's function?
Some sort of parent.dosome?
maybe create a class Object and define in its protoype the dosome() method.
var Object = new function() {}; //lots of stuff in here
Object.prototype.dosome = function(a,b) {
func(a,b);
}
//and then
var myObject = new Object();
I think you should read a little about JS OOP. ES6 adds some nice syntactic sugar that can help you achieve what you want in fewer lines of code. Read more here.
However, if you don't want to have problems with the prototype chains, here's a simpler way of achieving what you want:
function chain (baseFunc, func) {
return function () {
var args = [].slice.call(arguments, 0);
args.unshift(baseFunc);
return func.apply(this, args);
};
}
Usage:
var obj = {
doSome: function (a, b) { return a + b; }
};
obj.doSome(4, 5); // 9
obj.doSome = chain(obj.doSome, function (baseFunc, a, b) {
var result = baseFunc(a, b);
return result + 10;
});
obj.doSome(4, 5); // 19
You can go one step further and get rid of the assignment:
function extend (instance, method, func) {
instance[method] = chain(instance[method], func);
}
extend(obj, "doSome", function (baseFunc, a, b) {
var result = baseFunc(a, b);
return result + 2;
});
obj.doSome(4, 5); // 21

Categories