Anonymous arrow functions in objects [duplicate] - javascript

This question already has answers here:
Why does the logical or operator (||) with an empty arrow function (()=>{}) cause a SyntaxError?
(3 answers)
Closed 2 years ago.
How is it that this syntax works:
let foo = 0; // or 1
let bar = {
foo: foo || function (x) { return 'foo ' + x; }
};
// If foo is 0
bar.foo('bar'); // Returns 'foo bar'
// If foo is 1
bar.foo; // Returns 1
and this one doesn't:
let foo = 0; // or 1
let bar = {
foo: foo || (x) => { return 'foo ' + x; }
};
If I try to run the bottom example, I get the Malformed arrow function parameter list error in the console. How is it Malformed, and what would the correct syntax be to get the same functionality as the top example?

The issue is that the arrow function doesn't know how to group the parameters. You should wrap the function in parenthesis as such:
let foo = 1
let bar = {
foo: foo || (x => { return 'foo ' + x; })
};

I did'nt use js for a while but I think
let bar = {
foo: foo || (x => { 'foo' + x })
};
should do the job
greetings

Related

Why can't I return an arrow function? [duplicate]

This question already has answers here:
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 5 years ago.
I have a little higher-order sorta function here.
While this works as expected:
var square = (a) => a * a;
var callAndLog = (func) => {
return function () {
var res = func.apply(undefined, arguments);
console.log("Result is: " + res);
return res;
}
};
var squareAndLog = callAndLog(square);
squareAndLog(5); // Result is 25
This here, when i return an arrow function insted, doesn't work:
var square = (a) => a * a;
var callAndLog = (func) => {
return (() => {
var res = func.apply(undefined, arguments);
console.log("Result is: " + res);
return res;
})
};
var squareAndLog = callAndLog(square);
squareAndLog(5); // Result is NaN
I know that arrow functions are loose, that's why i try here returning it within the parantheses (). It doesn't work without them either.
From MDN:
An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target.
Arrow functions don't bind an arguments object to their body. Your function relies on the use of arguments, so it won't work as an arrow function.
As suggested in the comments above, you can use ...args instead:
var square = (a) => a * a;
var callAndLog = (func) => {
return (...args) => {
var res = func.apply(undefined, args);
console.log("Result is: " + res);
return res;
};
};
var squareAndLog = callAndLog(square);
squareAndLog(5);
I know that arrow functions are loose, that's why i try here returning it within the parantheses ().
Enclosing your arrow function in parentheses has no effect on its behavior. There are few (if any?) situations where it would.
Arrow functions doesn't have the arguments object, instead you can use the rest parameter syntax (...) like this:
var square = (a) => a * a;
var callAndLog = (func) => {
return ((...args) => {
var res = func.apply(undefined, args);
console.log("Result is: " + res);
return res;
})
};
var squareAndLog = callAndLog(square);
squareAndLog(5);

Calling inner function in Nested Scopes in JavaScript

I'm learning JS and am wondering, is there a way to return the function bar() or buz() by without returning foo()? For example, if I wanted to return the function bar(); to get 2, could I do that? Would it be something like foo().bar(); ?
// Nested Scopes
function foo() { // can only access itself
var a = 1;
function bar() { // access to foo(), not buz()
var b = 2;
function buz() { // access to bar() and foo()
var c = 3;
console.log(a, b, c); // 1, 2, 3
}
buz();
console.log(a, b); // 1, 2
}
bar();
console.log(a); // 1
}
foo(); // 1
Certainly. You can return an object at each stage which holds the function, or you can return the function itself. This utilizes what's called a closure.
function foo() {
var a = 1;
function bar() {
var b = 2;
function buz() {
var c = 3;
console.log(a, b, c);
}
console.log(a, b);
return { buz: buz };
}
console.log(a);
return { bar: bar };
}
foo().bar().buz();
You can do this, but it’s quite over-complicated.
The basic syntax is:
foo().bar().buz();
Where-ever you add another () after an existing one, it’ll print that level out. See the snippet for examples.
// Nested Scopes
function foo() { // can only access itself
var a = 1;
function bar() { // access to foo(), not buz()
var b = 2;
function buz() { // access to bar() and foo()
var c = 3;
return (function() {
console.log(a, b, c);
});
}
return (function() {
var tmp = function() {
console.log(a, b);
return {
buz: buz
};
};
tmp.buz = buz;
return tmp;
})();
}
return (function() {
var tmp = function() {
console.log(a);
return {
bar: bar
};
};
tmp.bar = bar;
return tmp;
})();
}
foo().bar().buz(); // (nothing)
foo().bar()().buz(); // 1, 2
foo()().bar()().buz(); // 1 // 1, 2
foo()().bar().buz()(); // 1 // 1, 2, 3
foo()().bar()().buz()(); // 1 // 1, 2 // 1, 2, 3
This kind of abuses the fact that you can assign properties to anything in JavaScript, including functions.
foo is a function that refers to the outer foo.
foo() is another function that refers to that inner tmp which has a bar property that refers to the inner bar function.
foo()() actually calls that inner tmp function but still leaves you with an object that has a bar property that again refers to the inner bar function.
This approach is basically the same for bar.
For buz, however, (something).buz() is just a function, without any extra properties and (something).buz()() doesn’t return anything, because that’s the final level.
you do this more like setting a variable.
var foo = {
bar: function() {
return 3;
}
}
console.log(foo.bar());

JavaScript compose functions

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?

double double parentheses javascript

I found this code in a book:
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2
What does last line mean?
The last line is doing an assignment and then calling the function.
Assignment happens first
(p.foo = o.foo)
Then call the function
(p.foo = o.foo)();
In this second call to foo, it is being called outside of the scope of p or o, so it's essentially the same as calling:
foo();

How to change a function accepted arguments after creating it on Javascript?

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

Categories