Prototypes of objects within objects - javascript

I'm trying to make a function that can be applied to a value returned from another function both within a function. Since that's probably a terrible explanation, here's a simplified sample:
function MainFnc() {
this.subFnc=function(a) {
return a*2
}
this.subFnc.subSubFnc=function(a) {
return this*a
}
}
This isn't my actual code - it's for a far better reason than multiplying numbers. This is just a simplified example of what I'm trying to achieve. My question is whether or not it's actually possible to go this deep, and if so how? The method I've portrayed in this sample code evidently does not work.
Thanks for any help.
Edit: Here's an example of it in use since not everyone understands clearly what I want to do with this:
anObject=new MainFnc;
alert(anObject.subFnc(2)); //returns 4
alert(anObject.subFnc(2).subSubFnc(2); //returns 8
This is not exactly what I'm doing, it's just easier to understand using simple multiplication.

This is about as close as you can get:
function foo(n){
this.value = n;
return this;
};
foo.prototype = {
valueOf : function(){
return this.value;
},
multiplyBy : function(n){
return new foo(this.value * n);
}
};
foo.prototype.toString = foo.prototype.valueOf;
var x = new foo(2);
var y = x.multiplyBy(2).multiplyBy(2).multiplyBy(2);
// y == 16

Update based on your comment:
MainFnc is an object which is created in a variable (ie MainVar). So if I wanted to try MainVar.subFnc(2) it'd return 4. If I wanted to try MainVar.subFnc(2).subSubFnc(2), however, it'd return 8.
Right now, you're returning a number from your subFnc, and so the expression MainVar.subFnc(2).subSubFnc(2) breaks down like this:
Look up the property subFnc on MainVar; it returns a function reference.
Call the function with this = MainVar; this returns the number 2.
Look up the property subSubFnc on the number 2; it returns undefined.
Call the function with this = 2; fails because you can't call undefined as a function.
More: You must remember this and Mythical Methods
To do what you're doing, you'd have to have subFnc return an object with function properties. You could do it like this:
function MainFnc(val) {
this.value = val;
this.mult=function(a) {
return new MainFnc(this.value * a);
};
this.div=function(a) {
return new MainFnc(this.value / a);
};
this.get = function() {
return this.value;
};
}
...and then call it like this:
var MainVar = new MainFnc(3);
alert(MainVar.mult(3).mult(4).div(6).get()); // alerts "6" (3 * 3 * 4 / 6 = 6)
Live example
Note the get function to return the underlying number. You might also add a toString:
this.toString = function() {
return String(this.value);
};
But the above isn't taking advantage of prototypical inheritance at all (and it will be important to, if you're creating all of those objects; we need to keep them lightweight); you might consider:
function MainFnc(val) {
this.value = val;
}
MainFnc.prototype.mult = function(a) {
return new MainFnc(this.value * a);
};
MainFnc.prototype.div = function(a) {
return new MainFnc(this.value / a);
};
MainFnc.prototype.get = function() {
return this.value;
};
MainFnc.prototype.toString = function() {
return String(this.value);
};
Original Answer:
With that code, if you did this:
var f = new MainFnc();
alert(f.subFnc(3)); // alerts "6"
alert(f.subFnc.subSubFnc(3)); // NaN
...because this inside subSubFnc when called like that is subFnc, and multipling a function reference tries to convert it to a number, which comes out NaN, and so the result of the multiplication is NaN.
Remember that in JavaScript, this is defined entirely by how a function is called, not where the function is defined. When you call a function via dotted notation (a.b();), the object you're looking up the property on becomes this within the function call, and so with a.b.c();, this within c() is b, not a. More: You must remember this and Mythical Methods

Related

In console I see "undefined" instead of 25. Why? How to see the correct result?

function Square(a) {
this.a = a ** 2;
return a;
}
const value = Square.call({}, 5);
console.log(value.a);
Actual -> value.a = undefined
Expected -> value.a = 25
You are returning a, so 5, not the object. And you pass an object {} for this, but it is not stored anywhere, you can't check it later. If you passed an object which you have access to afterwards, like diz below, its .a becomes 25 properly:
function Square(a) {
this.a = a ** 2;
return a;
}
const diz = {};
const value = Square.call(diz, 5);
console.log("Returned 'a', should be 5:",value);
console.log("Altered 'object.a', should be 25:",diz.a);
Alternatively you might have wanted to return this;:
function Square(a) {
this.a = a ** 2;
return this;
}
const value = Square.call({}, 5);
console.log(value.a);
I don't know why you use this, or where this object value is coming from. But let me explain. Your argument a can't be changed directly. You need to assign it to a variable, e.g. result to change and return it.
return result = a ** 2;
To call the function, you don't use .call. You simply call it in your console.log().
console.log(square(a));
The whole magic of this function you want to write:
function square(a) {
return result = a * a;
}
console.log(square(a));
// expected result is 25
I recommend a course on freeCodeCamp to learn the fundamentals of JavaScript. You can find it here.

javascript - object value only to be worked out when needed / called upon

for example, i have an object where the value of a key is yet to be known/computed but when i call that key for the first time it computes the value and replaces the calculation / function with the computed value. The point being that the value is only worked out when needed and then can be reused again without having to work it out again...
this is what i have so far...
function newobj() {
this.test=function(){
this.test=[1,2,3,4]//complex function in real world use
return this.test
}
}
a = new newobj()
a.test() //[1,2,3,4]
a.test() //not a function!
a.test //[1,2,3,4]
as you can see this requires parenthesis to call initially but not the second time, so this requires knowing whether it's already been called or not - not ideal
version 2
function newobj() {
this.test=function(){
var a=[1,2,3,4]
this.test=function(){return a}
return a
}
}
a = new newobj()
a.test() //[1,2,3,4]
a.test() //[1,2,3,4]
this just somehow doesn't seem the correct way to go about this.. but maybe it is?
apologies if this is a dumb question and thanks in advance for your help
You can use the ability of a getter to overwrite itself to create a "lazy" property whose value is only calculated the first time it's accessed:
There's a good example at MDN.
get test() {
delete this.test;
return this.test = someExpensiveFunctionCall();
}
Subsequent accesses to the property don't even use the getter - they retrieve the value direct from the object.
In your case since you're not using the usual getter syntax, you'd have to modify your function thus:
function newobj() {
Object.defineProperty(this, 'test', {
get: function() {
delete this.test;
return this.test = someExpensiveFunctionCall();
},
configurable: true
});
}
I think what you need is the Module Pattern. You could do
let Module = (function(){
let test = null;
return function(){
if(test == null){
console.log('initialized test');
test = [1, 2, 3, 4];
}
return test;
}
})();
let a = new Module();
console.log(a);
console.log(new Module());

Confusing function in javascript functional programming

I'm new to functional programming and I'm trying to learn it in javascript. I found some examples and wrote my own snippet, but I don't understand WHY it works. There is a function called whatTheHeckIsThis. Can someone tell me what it is doing or what its purpose is? Note that when running this code, the output is true.
function boolFlipper(someFn){
return function whatTheHeckIsThis(x,y){
return !someFn(x,y);
};
}
var checkStrings = function(x, y){
return x === y;
}
var flipperTester = boolFlipper(checkStrings);
var str1 = "this string";
var str2 = "that string";
console.log(flipperTester(str1, str2));
My confusion is why can't I just do this instead:
function boolFlipper(someFn){
return !someFn(x,y);
}
a reference to whatTheHeckIsthis() will be returned and stored into flipperTester
After this, flipperTester can be used like a function.
You can use this language feature to abstract some code.
Simple example:
function addTen(x) { return x + 10 }
function multiplyByTen(x) { return x * 10 }
...
var doMath
// somewhere a user selected something
if (userInputSaysAdd) doMath = addTen
if (userInputSaysMultiply) doMath = multiplyByTen
// this will be the choosen function
doMath(someValue)
Your second version doesn't work for 2 reasons:
The purpose of boolFlipper is to return a new function, which you can assign to another variable and later call.
Your function doesn't have x and y parameters.
To solve #2 you could write:
function boolFlipper(someFn, x, y) {
return !someFn(x, y);
}
You would then have to call it like:
console.log(boolFlipper(checkStrings, str1, str2));
But you still couldn't do:
flipperTester = boolFlipper(checkStrings);
The original snippet returns a closure, which is bound in the environment where someFn is equal to the function passed as an argument to bookFlipper(). You can then assign this function to a variable, and call it with new arguments, that are assigned to x and y, and then the the function saved in someFn() is called, the return value is negated with !, and this is returned.
For more information about closures, see How do JavaScript closures work?
In JavaScript functions are objects, so you can return them. When you return a function you are getting a function object, so you can call it as any other function. For example:
function myFun() {
return function() {
console.log("test");
};
}
var functionInside = myFun();
/* This is like doing:
var functionInside = function() {
console.log("test");
};
*/
functionInside(); // This will execute the function.
Example with your code:
This variable:
var flipperTester = boolFlipper(checkStrings);
contains a function like this:
var flipperTester = function (x,y) {
return !someFn(x,y);
}
And this is something similar to
function flipperTester(x,y) {
return !someFn(x,y);
}
So when you do:
flipperTester(str1, str2)
You are executing that function. The variable "someFn" inside there is the function "checkStrings", because you passed it when you initialize flipperTester variable.
boolFlipper is, for our purposes here, a function decorator: it takes a function and modifies it to do something else. A more instructive example might be a logging function:
var alsoLogs = f => (...args) => {
var result = f(...args);
console.log(result);
return result;
};
// now we have a function that adds 2 numbers:
var add = function add(a, b) { return a + b; };
// and we want to also log the result
var addAndLog = alsoLogs(add); // addAndLog is a function, would be the whatTheHeckIsThis from your example
addAndLog(2, 3); // logs 5 to the console
If you don't understand all the ES6 syntax that's ok, just understand that alsoLogs take a function f and returns a function that does the exact same thing as f but also logs the result to the console.
Since we as programmers are lazy, we don't want to have to write functions to glue together other functions every time we want to do this, so we write a function to do it for us, compose.
So now we can just say something like:
var addAndLog = R.compose(console.log, add);
addAndLog(2, 3); // logs 5 to the console

What is an example of an impure function in JavaScript

Having seen a lot of pure functions and how they have no side effects, what would be an example of an impure function, which is always been antagonized as unstable and major source of error?
For example an impure function that has a side effect on a variable outside of its own scope:
var count = 0;
function increaseCount(val) {
count += val;
}
Or a function that returns different values for the same input because it evaluates a variable that is not given as parameter:
var count = 0;
function getSomething() {
return count > 0;
}
A pure function doesn’t depend on and doesn’t modify the states of variables out of its scope.
Concretely, that means a pure function always returns the same result given same parameters. Its execution doesn’t depend on the state of the system.
var values = { a: 1 };
function impureFunction ( items ) {
var b = 1;
items.a = items.a * b + 2;
return items.a;
}
var c = impureFunction( values );
// Now `values.a` is 3, the impure function modifies it.
Here we modify the attributes of the given object. Hence we modify the object which lies outside of the scope of our function: the function is impure.
var values = { a: 1 };
function pureFunction ( a ) {
var b = 1;
a = a * b + 2;
return a;
}
var c = pureFunction( values.a );
we simply modify the parameter which is in the scope of the function, nothing is modified outside!
var values = { a: 1 };
var b = 1;
function impureFunction ( a ) {
a = a * b + 2;
return a;
}
var c = impureFunction( values.a );
// Actually, the value of `c` will depend on the value of `b`.
// In a bigger codebase, you may forget about that, which may
// surprise you because the result can vary implicitly.
Here, b is not in the scope of the function. The result will depend on the context: surprises expected!
var values = { a: 1 };
var b = 1;
function pureFunction ( a, c ) {
a = a * c + 2;
return a;
}
var c = pureFunction( values.a, b );
// Here it's made clear that the value of `c` will depend on
// the value of `b`.
Reference : For more details, click here
Math.random() is an impure function; it changes the internal state of the Math object so you get different values on successive calls. console.log() and alert() are impure functions because they have side effects (although they generate the same behavior and always return the same value for identical calls).
Any function that changes the internal state of one of its arguments or the value of some external variable is an impure function. This includes closures where calling a method changes the internal state of the closure itself:
let nextInt = (function() {
var i = 0;
return function() {
return i++;
};
})();
let a = nextInt(); // sets a to 0
let b = nextInt(); // sets b to 1
// etc.
Where'd you get the idea that impure functions are always considered a bad thing?
Impure functon is a function which returns different result for
same input parameters, that is to say that it depends on some state;
Function that may return same result for same input parameters, but
that mutates other state object. object that it does not depends but others do // causes side effects
example:
1)
var toggled = false; /* state */
/*impure function*/
function impureFn(number){
if(number%2 == 0)
toggled = true;
return toggled;
}
/*Execute this in order */
impureFn(5) // returns false
impureFn(2) //returns true
impureFn(5) // now returns true
An example i can think of (that is indeed quite confusing) is Array#reverse(). Instead of returning a new array, it modifies it in place while returning the original array.
Some other array functions do this as well, such as splice, push, shift, pop, unshift.
pure function (get argument and return new value):
function (objectArgument) {
return {
value: objectArgument.value + 123,
// other arguments
};
}
impure function (get argument, modified it and return modified object):
function (objectArgument) {
objectArgument.value += 123;
return objectArgument;
}

Work around without using javascript object in this case

I was used to do programming using python but I am using javascript for some project now. In python, OOP concept was little easy than javascript which I am reading right now. That being said, I am not so comfortable right now using javascript object and prototypes. In the meanwhile, can I achieve the following without using object? I am not a pure programmer (always took it as hobby) so please bear with me:
function func1(arg1){
does item..1..for eg...var result=arg1*2;
does item..2..for eg...var resultSq=arg*arg;
......
}
I want other function, say func2 which when calls func1; funct1 responds just by performing item...1 and returning the result.
In other words, I want to detect who called the function and have if statements to change the execution
Sorry if it is too simple.
Identifying who the Caller is:
<script>
function func1()
{
if(arguments.callee.caller.toString().indexOf(" test()") != -1)
//May be optimizable with a name property
{
return "I was called from test()";
}
if(arguments.callee.caller.toString().indexOf(" test2()") != -1)
//May be optimizable with a name property
{
return "I was called from test2()";
}
}
function test()
{
return func1();
}
function test2()
{
return func1();
}
alert(test());
</script>
Reference: How do you find out the caller function in JavaScript?
Passing an ID:
As the question is actually how to execute differently depending on who the caller is, you need to have an if statement, that checks what action should be executed.
function doSomething(actionNumber)
{
if(actionNumber == 1)
{
return 1;
}
else if(actionNumber == 2)
{
return 1;
}
//etc...
}
function2()
{
doSomething(1);
}
There are a number of patterns to create and handle objects, here is one that I use a lot.
JavaScript prototypal OOP
var ConstructFoo = function () { //capitalise constructor names
var x = "my private variable";//remember, JS has FUNCTIONAL scope
this.y = 10; //we can read and write to this outside of this function
}
ConstructFoo.prototype.barMethod = function () {
return this.y * 10;
}
var bash = new ConstructFoo();//new keyword is syntactic sugar for creating a new instance
alert(bash.y);//will alert 10
alert(bash.x);//ERROR, this is undefined
alert(bash.barMethod());//will alert 100
var baz = new ConstructFoo(); //new instance, lets prove it
alert(bash === baz); //will alert false
bash = "";
alert(bash.y);//ERROR, this is undefined
alert(baz.y);//alerts 10
Not to be confused with a JavaScript object:
var foo = {
funcA: function (params) {
var bar = 2;
//etc
return bar;
},
funcB: function (param) {
var bar = param * 2;
//etc
return bar;
}
};
foo.funcA(7);//returns 2
foo.funcB(2); //returns 4
This is a static object. You don't create new instances of it. If you change foo.funcA elsewhere, it will affect all code using that function.
Suggested reading: JavaScript Patterns by O'Reilly

Categories

Resources