Calling function on function result like jQuery does - javascript

I am trying to build two functions to work like jQuery functions work, for example: jQuery( 'select').val();
This works:
function func(a) {
console.log(1);
return a;
}
func.sub = function(n) {
console.log(2);
}
func.sub(2);
But this doesn't:
function func(a) {
console.log(1);
return a;
}
func.sub = function(n) {
console.log(2);
//return func result[n];
}
func([1,2,3]).sub(2);
How can I make this second code work and read func() result on sub()?

You need to have func return an object that has a method sub.
function Subbable(x) {
this.value = x;
}
Subbable.prototype.sub = function(b) {
return this.value - b;
}
function func(a) {
return new Subbable(a);
}
func(10).sub(2)
// 8
jQuery's $(...) typically returns a jQuery object that contains a collection of the selected nodes, and whose prototype has all the nice goodies like .attr and .css.

Related

Returning a function with the arguments reversed

The code that I am practicing with is where I have a function called InReverse. This function accepts a function as an argument and returns a function. When the function returned is invoked, it reverses the order of the arguments.
When the returned functions are returned:
const catDog = ('cat', 'dog') => returns ('dog cat')
What I have rewritten out so far is:
function inReverse (func) {
return function (...arguments) {
return arguments.map((element) => {
element.reverse();
});
}
}
Any guidance would be appreciated!
You need to simply call the input function inside the newly created anonymous function.
For example this works:
function inReverse(f) {
return function () {
let args = [...arguments].reverse();
return f.apply(this, args);
}
}
So for example if you have subtract function like this:
function subtract(a, b) {
return a-b;
}
subtract(1, 10); will be -9 as expected.
and inReverse(subtract)(1, 10) will be 9 as expected.
Not sure why you're using map, just call reverse right on the arguments array. Also you weren't calling func:
function inReverse(func) {
return function(...args) {
return func(...args.reverse());
};
}
(Notice that arguments is a reserved identifier in strict mode, you should name your parameter for something else)
Not sure, why you are using map method, just use reverse method in your function right on the arguments. Reference : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse?retiredLocale=id
Just reverse the arguments, and use func.apply(this, arr)
function inReverse(func) {
return function() {
var args = Array.prototype.slice.call(arguments)
args = args.reverse();
return func.apply(this, args);
}
}
function div(a, b) {
return a / b
}
console.log(div(1, 2))
console.log(inReverse(div)(1, 2))

create copy of already made function with new parameters?

I have a function freq01(), when a button is clicked I want a function(new) to create a copy of function freq01(), with new parameters. I have no idea where to start or if JS can create a function from a function.
All variables have been created. Please point me in the right direction...!
The code below is to save the checked radio button value to an array.
function freq01(){
if (document.getElementById("w01").checked){
incFreq = document.getElementById("w01").value;
}
else if (document.getElementById("f01").checked){
incFreq = document.getElementById("f01").value;
}
else if (document.getElementById("m01").checked){
incFreq = document.getElementById("m01").value;
}
}
I have no idea ... if JS can create a function from a function.
To answer this part of your question, yes Javascript can create a function from a function. Any function can return another function, and the typical ways to do this would be to create a factory function, or use function currying to create new functions:
Factory
A function that returns another function. Due to Javascript closures, you can set "private" variables that the returned function can see, but the calling function cannot access:
function addTwoFactory() {
let a = 2;
return function(b) {
return a + b;
}
}
let f1 = addTwoFactory();
let f2 = addTwoFactory();
console.log(f1(3)); // 5
console.log(f2(3)); // 5
Can also make configurable factories that can create different sorts of methods:
function makeAdder(a) {
return function(b) {
return a + b;
}
}
let addTwo = adderFactory(2);
let addThree = adderFactory(3);
console.log(addTwo(3)); // 5
console.log(addThree(3)); // 6
Currying
Function currying is the idea of taking a base function that takes several parameters, and "baking in" one of the parameters, to reuse more easily:
function adder(a, b) {
return a + b;
}
function makeAdder(a) {
return function(b) {
return adder(a, b);
}
}
let addTwo = makeAdder(2);
console.log(addTwo(3)); // 5
You can try to use bind https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
var freq01 = freqBase.bind(null, "w01","f01","m01");
function createNewFunc(i){
return freqBase.bind(null, "w0"+i,"f0"+i,"m0"+i);
}
function freqBase(a,b,c){
if (document.getElementById(a).checked){
incFreq = document.getElementById(a).value;
}
else if (document.getElementById(b).checked){
incFreq = document.getElementById(b).value;
}
else if (document.getElementById(c).checked){
incFreq = document.getElementById(c).value;
}
}
var func2 = createNewFunc(2);
var func3 = createNewFunc(3);
func2();
func2();
func2();
func3();
func2();
Other idea is to just return new function
var newf1 = function createNewFunc(i){
return function(){ return i;}
}
newf1(1)();
newf1(1)();
newf1(1)();
shorter version could be:
a = (i)=> ()=> { return i; }
or more readable
const f2=function createNew(i){
return ()=> { return i; }
};
const res = f2(1)();

Is it possible to get all defined functions inside other function?

Is it possible inside list to get all available functions - a, b, c without their enumeration and without using window?
(function(){
function a() { return 1; }
function b() { return 2; }
function c() { return 3; }
function list()
{
return [a, b, c];
}
})();
No, it's not possible with functions declared directly in the current scope.
To achieve this, you would have to assign the functions to some property of the scope, i.e.:
(function() {
let funcs = {};
funcs.a = function() {
return 1;
}
...
function list() {
return Object.values(funcs);
}
});
NB: Object.values is ES7, in ES6 use:
return Object.keys(funcs).map(k => funcs[k]);
or in ES2015 or earlier use:
return Object.keys(funcs).map(function(k) { return funcs[k] });
If you haven't even got Object.keys, give up... ;)
I understand where you are trying to get. So perhaps this is the closest thing to what you requested, without using the window name (the same object though):
// define a non-anonymous function in the global scope
// this function contains all the functions you need to enumerate
function non_anon() {
function a() { return 1; }
function b() { return 2; }
function c() { return 3; }
function list() { return [a, b, c]; }
// you need to return your `list` function
// i.e. the one that aggregates all the functions in this scope
return list;
}
// since in here the purpose is to access the global object,
// instead of using the `window` name, you may use `this`
for (var gobj in this) {
// from the global scope print only the objects that matter to you
switch (gobj) {
case 'non_anon':
console.info(gobj, typeof this.gobj);
console.log(
// since you need to execute the function you just found
// together with the function returned by its scope (in order to `list`)
// concatenate its name to a double pair of `()` and...
eval(gobj + '()()') // evil wins
);
break;
}
}

Pass one object result to another object function like chain

I have one simple object calculation function .I was pass the object resultant data in to another object function like the chain reaction
example like:
str.replace().replace().replace() They will pass the resultant data of first replace to 2nd replace like the chain reaction.
So i want to created the below code .But not working in my case .
See the below snippet
var m=function(data){
return {
str :data,
plus:function(b){
this.str = this.str+b;
return this.str;
},
min:function(a){
this.str = this.str-a
return this.str;
}
}
}
console.log(m(5).plus(1).min(3))
If 5 add with 1 is 6 .Then pass the 6 into min() function for reduce 3 .finally console.log result 3 .But It have some here .Please help to solve my problem.
Thanks
I suggest to use an object and return that object after a method call. For better use, you could implement toString and valueOf methods to use the return value directly.
What you need is to return the whole object, for all methods which a chainable.
var m = function(value){
var obj = {
value: value,
plus: function (b) {
obj.value += b;
return obj;
},
min: function(a) {
obj.value -= a;
return obj;
},
toString: function () { return obj.value; },
valueOf: function () { return obj.value; }
}
return obj;
}
console.log(m(5).plus(1).min(3).value);
alert(m(5).plus(1).min(3));
console.log(m(3).plus(7) - m(5).min(1));
var m=function(data){
return {
str :data,
plus:function(b){
this.str = this.str+b;
return this;
},
min:function(a){
this.str = this.str-a
return this;
}
}
}
console.log(m(5).plus(1).min(3).str)
For creating chain like method calls you need to return 'this' from the function after which you want to the chain to continue
Another closer way, we can return this separately, at initialisation, and every other method calls.
Doing it this way is a real chain, as this called in the plus and min function is the incoming object, it's not a recomposition.
We often see both styles.
function m(n) {
this.value = n.value
this.plus = (n) => {this.value = this.value + n.value; return this}
this.min = (n) => {this.value = this.value - n.value; return this}
return this // Only at initialisation
}
console.log(m({value: 5}).plus({value: 1}).min({value: 3}).value)

Wrapper function in Javascript

I understand wrapper would be something like
var str = 'Hello World'; // assigning string to a variable
console.log(str); // 'Hello World'
var str2 = new String('Hello World') // Creating a wrapper function
str2.valueOf() // 'Hello World'
By that logic, can the below example also be considered a wrapper function
function SuperOuterAdd(a, b){
console.log('Wrapper 2');
return OuterAdd(a, b);
}
function OuterAdd(a, b){
console.log('Wrapper 1');
return add(a, b);
}
function add(a, b){
return parseInt(a) + parseInt(b);
}
There's no language definition of wrapper function in JavaScript, and from your code, new String('Hello World'), is an instantiation of a string object - I don't see how that would be considered a wrapper function by any logic at all.
A wrapper function is a design concept where a very minimal function is using another function to do it's "work" for it, sometimes using a slightly different set of arguments.
for example:
function power(x, y) {
var res = 1;
while(y--) {
res *= x;
}
return res;
}
function square(x) {
return power(x, 2);
}
In the code above square is a wrapper function.
Wrappers are a loose term for a function that simply returns a value, with no computation. They are useful when we need a value, but not right away. Maybe the result is not ready yet when you define it, or you need some binding for the function to work (use of this).
Neither of the examples you provided is a wrapper function. The first one is simply an object instantiation (you're not even creating a function). It just so happens that the String constructor can take a string literal as an argument, which means it can work like the identity function. In the second, it's just some more elaborate contraption, but it's still function calling and computing things.
In general, wrapper functions are pretty useless out of context, and they're mostly a Javascript-specific thing, but consider the following:
let foo = null;
fetch('/my/api/call').then(function(res) {
foo = res;
getFoo(); // => [your object]
});
getFoo(); // => null
function getFoo() {
return foo;
}
Here is the example:
function SimpleWrapper() {
var self = this;
initialize();
function initialize() {
self.SuperOuterAdd = SuperOuterAdd;
self.OuterAdd = OuterAdd;
}
function SuperOuterAdd(a, b){
console.log('Wrapper 2');
return OuterAdd(a, b);
}
function OuterAdd(a, b){
console.log('Wrapper 1');
return _add(a, b);
}
function _add(a, b){
return parseInt(a) + parseInt(b);
}
}

Categories