How to access grand-child's variable in a closure - javascript

I want to retrieve the values of a and b from p in the code given below. I would also like to run the function z from p. How do I achieve this?
function x() {
var a = 10;
return function y() {
var b = 20;
return function z() {
console.log(a, b);
}
}
}
const p = x();
I'm new to JS.

function x() {
var a = 10;
return function y() {
var b = 20;
return function z() {
console.log(a,b)
}
}
}
// get function z
const result = x()();
console.log(result)
// get a,b
result()
Calling x returns function y, calling y returns function z i.e. x()();
By calling function z, you can get a,b (return or console) i.e. x()()();

Related

How do I call a JavaScript method based on a variable value?

I have method a(), method b(), and method c(). I will get a response message from server, which contains a or b or c and so on.
If the response message is a, then I need to call method a().
If the response message is b, then I need to call method b()
And so on...
I don't want to write any if else conditions or switch case to identify the method.
I don't want to do this:
if(res == 'a')
a();
else if(res == 'b')
b();
Instead of that I need something like reflections in Java.
If you have defined the function in Global/window Scope then you can directly use res variable
window[res]();
Otherwise define the function in object and then use it
var obj = {
a : function(){},
b : function(){}
}
obj[res]();
You could use an object and store the function inside, like
var functions = {
a: function () {},
b: function () {},
c: function () {}
default: function () {} // fall back
}
Usage:
functions[res]();
Or with default
(functions[res] || functions.default)();
For this purpose you can define a class that allows you to define and call methods, and determine the calling context:
var MethodsWorker = function () {
this._context = window;
this._methods = {};
}
MethodsWorker.prototype.setContext = function (context) {
this._context = context;
}
MethodsWorker.prototype.defineMethod = function (name, method) {
this._methods[name] = method;
};
MethodsWorker.prototype.invoke = function (methodName, args) {
var method = this._methods[methodName];
if (!method) { throw {}; }
return method.apply(this._context, args);
};
Usage:
var methodsWorker = new MethodsWorker ();
methodsWorker.setContext(Math);
methodsWorker.defineMethod('sqrtOfSum', function() {
var sum = 0;
for (var i = 0, n = arguments.length; i < n; i++) {
sum += arguments[i];
}
return this.sqrt(sum);
});
var result = methodsWorker.invoke('sqrtOfSum', [1, 2, 3]);
alert (result);

Javascript: return multiple values from different functions

I am trying to return multiple values from different functions.
The starting point is a bidimensional array. An example of the code is:
var items = [[0,1],[1,2],[0,2]];
var a;
var b;
function first() {
a = items[Math.floor(Math.random() * items.length)];
return a;
}
function second() {
b = a[Math.floor(Math.random() * 2)];
return b;
}
function third (){
first();
second();
}
third();
If I write the code outside the functions, everything works fine. When I use functions and replace return with console.log, it works. If I use functions and return (as in the code reported above), it gives me undefined. I didn't find solutions. Why the code isn't working?
Thanks in advance
If you are declaring variable a and b outside function(like in your code) than there is no need to return the values. a and b will get defined.
But if you are not declaring it outside, then store the return values in array variable.
var items = [[0,1],[1,2],[0,2]];
function first() {
a = items[Math.floor(Math.random() * items.length)];
return a;
}
function second() {
b = a[Math.floor(Math.random() * 2)];
return b;
}
function third (){
var a = first();
var b = second();
var arr = [];
arr.push(a);
arr.push(b);
return arr
}
var t = third();
console.log(t[0], t[1]);
If you want third to return values, add a return in it.
function third (){
var a = [];
a.push(first())
a.push(second())
return a;
}
Maybe you want something like
function third (){
return {a: first(), b: second()};
}
then
var t = third()
console.log(t.a, t.b)
or if you're running on ES6
var {a,b} = third()
console.log(a, b)
see Destructuring assignment for further details

New method does not see "this" (JavaScript)

Making a calculator that accepts new methods. But when I add a new method it does not see object's "this". Why Console.log returns "undefined"?
function Calculator() {
this.numbers = function() {
this.numberOne = 2;
this.numberTwo = 5;
},
this.addMethod = function(op, func) {
this[op] = func(this.numberOne, this.numberTwo);
// WHY LOG RETURNS "undefined"?
console.log(this.numberOne);
}
}
let calc = new Calculator();
calc.addMethod("/", (a, b) => (a / b));
document.write(calc["/"]);
You did not define this.numberOne and this.numberTwo before you tried to call the function on it. Moreover, you are printing this.one which is never defined in your code.
If you tried the following snippet:
function Calculator() {
this.numbers = function() {
this.numberOne = 2;
this.numberTwo = 5;
},
this.addMethod = function(op, func) {
this[op] = func(this.numberOne, this.numberTwo);
// WHY LOG RETURNS "undefined"?
console.log(this.numberOne);
}
}
let calc = new Calculator();
calc.numbers();
calc.addMethod("/", (a, b) => (a / b)); // 2/5
document.write(calc["/"]);
Then the code will work as expected because calc.numberOne and calc.numberTwo are defined
Your numbers were not getting initialized.
Also you used this.one what's that? Did you mean numberOne.
Check out the working code below :
function Calculator() {
this.numberOne = 2;
this.numberTwo = 5;
this.addMethod = function(op, func) {
this[op] = func(this.numberOne, this.numberTwo);
// WHY LOG RETURNS "undefined"?
console.log(this.numberOne, this.numberTwo );
}
}
let calc = new Calculator();
calc.addMethod("/", (a, b) => (a / b));
document.write(calc["/"]);

variable within a object not updating in javascript

I have an object which is initialized like
var x = function(){
var result = 5,
clear = function(){
result = 0;
};
return {
result: result,
clear: clear
}
}
I am later creating a new instance of x using var y = new x();
but when i try setting the value y.result = 5; and want to clear the result value to 0 I call y.clear();
However it is not resetting the y.result to 0... Not sure why?
Anything that i am doing wrong?
Within your function:
var x = function(){
var result = 5,
clear = function(){
result = 0;
The identifier result in this function has a closure to the variable result in the outer function (i.e. outer execution context).
};
return {
result: result,
That assigns the value of the variable named result to the object property named result.
clear: clear
}
}
So later when you call y.clear() you are setting the value of the variable held in the closure, which does not update the object property named result.
If you want x to be a constructor, then:
function X() {
this.result = 5;
this.clear = function() {
this.result = 0;
}
}
So now:
var y = new X();
y.clear();
console.log(y.result); // 0
Note that it is convention for constructors to have a name starting with a capital letter. You can learn more about how to use the new operator on MDN.
To leverage ECMAScript inheritance, put the clear function on the constructor's prototype so that all instances inherit the one method, rather than each having its own:
function X() {
this.result = 5;
}
X.prototype.clear = function() {
this.result = 0;
}
The problem is that numbers are referenced by value. Assigning value to result variable from clear function won't change value of result on new x instance.
There are several ways to go about this:
Store data on this, then modify it there inside constructor and method, I find it easier to understand and more readable. This is probably what you wanted to begin with:
function x () {
this.result = 5;
}
x.prototype.clear = function () {
this.result = 0;
}
var z = new x();
// z.result === 5
z.clear()
// z.result === 0;
Define getter and setter on returned object, so instance result would return\set closured variable:
function x () {
var result = 5;
function clear () {
result = 0;
}
var out = {
clear: clear
};
Object.defineProperty(out, "result", {
get: function () {
return result;
},
set: function (value) {
result = value;
}
});
return out;
}
var z = new x();
// z.result === 5
z.clear()
// z.result === 0;
z.result = 10
// z.result === 10;
z.clear()
// z.result === 0;

Is it possible to /manipulate/ functions as it is strings?

var myString = '';
myString += 'foo';
myString += 'bar';
myString = myString.replace(/oba/, 'qux');
console.log(myString) // produces "foquxr"
Is there any way to likewise tinker around with functions, like, say, turning function(a) { a += 'b'; return a; } info function(a) { a += 'b'; console.log(a); return a + 'c'; }?
You can compose functions thus
// (compose(f, g))(x, y, ...) is the same as f(g(x, y, ...))
function compose(f, g) {
return function (var_args) {
return f.call(this, g.apply(this, arguments));
};
}
so
var f = compose(
function (x) { console.log(x); return x + 'c'; },
function (a) { a += 'b'; return a; });
lets you combine two small functions to get a function that behaves like
function(a) { a += 'b'; console.log(a); return a + 'c'; }
You could achieve this (without using eval) by getting the function's body from its declaration, manipulating it as needed, and redefining it by means of the Function() constructor:
function myFunction(a) { a += 'b'; return a; }
function changeFunction(){
var func = window['myFunction'].toString();
var body = func.substring(func.indexOf("{")+1, func.lastIndexOf("}"));
body = body.replace("return a;", "console.log(a); return a + 'c';");
window.myFunction = Function("a", body);
}​
Here's a JSFiddle

Categories

Resources