Understanding the JS code while setting up redis with Mongoose - javascript

I was trying to understand caching in NodeJS using redis.
In the lecture, the instructor told that best place to setup caching would be just before exec function in mongoose.
So in order to do that he did
const mongoose = require('mongoose')
const exec = mongoose.Query.prototype.exec;
//Redis logic
mongoose.Query.prototype.exec = function () {
console.log("i am here")
return exec.apply(this, argument);
}
1st: What will classify mongoose.Query.prototype.exec; as? value type or reference type? Because if it is a reference type then when we change mongoose.Query.prototype.exec = function then shouldn't its value change as well?
2nd I am unable to comprehend this line here return exec.apply(this, argument); Can someone explain this in stretch i.e this in apply points to where? and he is passing argument (this, argument); where does that Argument come from?
Can someone please help me out by answering both the above question?

What will classify mongoose.Query.prototype.exec; as? value type or
reference type? Because if it is a reference type then when we change
mongoose.Query.prototype.exec = function
exec is of reference type, but it is assigned the value of another reference variable mongoose.Query.prototype.exec. You can think of it like this : mongoose.Query.prototype.exec is itself pointing to an object (a Function object) in memory, and now after the assignment, exec is also pointing to the same object - in other words, the memory address of the object is copied (by value) from mongoose.Query.prototype.exec to exec during assignment. So the value of the variable mongoose.Query.prototype.exec itself i.e. the memory address stored in it, can be changed without affecting the other variable exec. They both will just end up pointing to two different objects.
Can someone explain this in stretch i.e this in apply points to where?
In this case, it'll be the object on which this function will be invoked i.e. the Query instance.
and he is passing argument (this, argument); where does that Argument come from?
Unless there is some code you missed to copy paste in the question, argument appears to be a typo. He was probably referring to the built-in object arguments which is accessible inside every function and consists of the arguments passed to the function. Here is a reference.
At a high level, what the instructor is trying to do is to override the built-in behavior of the function Query.exec() to add some of his own custom processing. He first creates a "backup" of the original function, then points Query.exec to his custom function which adds the custom processing (the log statement) and then hands over control to the backup i.e. proceed with built-in behavior. Whoever invokes exec() on a Query instance after this point will see the overridden functionality - first a log statement, then built-in behavior of exec()

Related

How to find if variable call or function call?

Note: This question is based on firestore admin SDK, but it is a general JS question.
Working with JS firestore admin SDK, this puzzled me a lot. Compare these 2 examples
Request a database value
admin.firestore().collection('my-Col').doc('my-doc').get().then(...)
Get a server timestamp is
admin.firestore.FieldValue.serverTimestamp()
In 1st example, it is admin.firestore() , in 2nd example it is admin.firestore
How it is possible to have a first behavior if called as function, another behavior if called as object key?
Maybe admin.firestore() calls a constructor... But then, how to get static value (whatever constructor called before or not) by doing admin.firestore?
From #jonrsharpe:
"A JavaScript function can also have arbitrary properties"
You gave me the tip! Built a small example to test
const bill = () => ({
friend: "boule"
});
bill.name = "bill";
const base = {
bill: bill
};
console.log(base.bill().friend);
// -> boule
console.log(base.bill.name);
// -> bill
This is what I was looking for. Thanks a lot.
In Javascript, functions can also have properties on their own. In javascript, you have either primitive values (boolean, numbers, strings, null and undefined) or (all the rest) objects. And functions are no exception. They are called first-class objects. A first-class object is, quoting from Wikipedia:
In programming language design, a first-class citizen (also type, object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, modified, and assigned to a variable.
When you do something like:
admin.firestore()
You are getting the value returned by firestore. And it happens, that this returned value has a property on it named collection (a function).
However, when you do:
admin.firestore.FieldValue
You are accessing the FieldValue property on firestore.

Why is arrow function sent as a parameter when it simply returns the value it takes as is?

I am new to JavaScript and I am learning React using the following tutorial.
It also teaches to use Alt as a state management library and my question is related to the connect method syntax. I am not explaining the problem in detail as I believe my question is only related to understanding the syntax.
I understand that here connect passes comma separated parameters as props to the component App. I however do not understand the first parameter.
The arrow functions I have come across all use {} after => such as () => {}, where parameters will be in () and body of the function will be in {}
My understanding of ({lanes}) => ({lanes}) is that this is a function that takes an array of objects named lanes and returns the same array .The code snippet is as below:
export default connect(({lanes}) => ({lanes}), {
LaneActions
})(App)
My questions are:
Am I right that the first parameter is indeed a function?
is lanes enclosed in {} to specify it's an array? If no, what does it represent?
If 1. is right, why pass a function that passes the parameter as is. Why not write connect as connect(lanes,LaneActions)(App) or connect({lanes},LaneActions)(App)
Would enclosing lanes in {} make a difference and what is it?
If 1. is wrong please explain what the first parameter means.
Yes, that is indeed an arrow function.
No, that is not an "array" in JS (although if you've used PHP, you might mistakenly call it that, since the PHP community often uses "(associative) array" for this concept). That's an "object" in JS jargon, i.e., a key-value data structure (whereas in JS, arrays are numerically indexed). Specifically, the left-hand side is a new feature called "destructuring arguments", which takes an object and pulls out specific keys into local variables. On the right-hand side, there's an object literal, creating a new object based on local data (note that the value is omitted, a trick possible in recent JS).
Presumably because connect expects a callback as the first argument, and would break if you passed a non-function. Also, note that this isn't plain passthrough; it strips every key except lanes from the first argument, before returning it.
Since (1) is right, no answer needed here.
5 & 6: These are a bit broad. I'd recommend asking a new question or checking MDN's page on arrow functions if you want to find out all there is to know. To answer for this specific case: the () on the argument is needed because the arguments are more complex than a single identifier, the {} in the arguments are for destructuring, the () on the body is to distinguish between an object literal and a block consisting only of the single statement lanes, and the {} in the body creates an object literal.
If you're wondering exactly what the (somewhat densely-coded) arrow function does, by the way, it does roughly the same thing as the following (give or take a few currently-irrelevant quirks of arrow functions):
function(obj) {
return { lanes: obj.lanes };
}

Can't use String.prototype.match as function for Array.some?

This doesn't work:
var s = '^foo';
console.log(['boot', 'foot'].some(s.match));
Uncaught TypeError: String.prototype.match called on null or undefined
But this does:
var s = '^foo';
console.log(['boot', 'foot'].some(function(i) { return i.match(s) }));
Why is this? I imagine somehow the String.prototype.match function is too "primitive" or something, but why exactly? Since I'm not using ES2015, the second version seems quite verbose. Is there an alternative?
EDIT
When I wrote the above, I actually got it backwards compared to my actual need, which was matching one string against a number of regexes. But thanks to the great answers and comments below, I get it: [/^foo/, /^boo/].some(''.match, 'boot').
Note: The value of this is determined by how the function is called! (exception: bound and arrow functions)
If you pass s.match to .some, then the function will be called with this set to the global object (e.g. window) not the string it "belongs" to.
I.e. it would be equivalent to this:
String.prototype.match.call(window, 'foo')
This cannot work because this has to refer to a string object.
You could solve this by binding the function to a specific this value:
['boot', 'foot'].some(s.match.bind(s));
Learn more about this:
MDN - this
You Don't Know JS: this or That?
How to access the correct `this` context inside a callback?
A function value in Javascript does not bring its object along with it. The value of s.match is a plain function value, with no knowledge that you happened to find it attached to s. In fact, no matter what String you access it through, it's always the same function value:
"foo".match === "bar".match
//= true
When you call a function through an object, Javascript sets this to that object for the duration of the function call. But as soon as anything comes between retrieving the function value and calling it, any object association is lost.
You can create a function that does remember a specific this value using bind, as in #Felix King's answer. someFunction.bind(someObject) has approximately the same meaning as function(arg1, arg2,...) { return someObject.someFunction(arg1, arg2,...); }, but it automatically handles the number of parameters properly.

Using the Javascript slice() method with no arguments

I'm currently reading through this jquery masking plugin to try and understand how it works, and in numerous places the author calls the slice() function passing no arguments to it. For instance here the _buffer variable is slice()d, and _buffer.slice() and _buffer seem to hold the same values.
Is there any reason for doing this, or is the author just making the code more complicated than it should be?
//functionality fn
function unmaskedvalue($input, skipDatepickerCheck) {
var input = $input[0];
if (tests && (skipDatepickerCheck === true || !$input.hasClass('hasDatepicker'))) {
var buffer = _buffer.slice();
checkVal(input, buffer);
return $.map(buffer, function(element, index) {
return isMask(index) && element != getBufferElement(_buffer.slice(), index) ? element : null; }).join('');
}
else {
return input._valueGet();
}
}
The .slice() method makes a (shallow) copy of an array, and takes parameters to indicate which subset of the source array to copy. Calling it with no arguments just copies the entire array. That is:
_buffer.slice();
// is equivalent to
_buffer.slice(0);
// also equivalent to
_buffer.slice(0, _buffer.length);
EDIT: Isn't the start index mandatory? Yes. And no. Sort of. JavaScript references (like MDN) usually say that .slice() requires at least one argument, the start index. Calling .slice() with no arguments is like saying .slice(undefined). In the ECMAScript Language Spec, step 5 in the .slice() algorithm says "Let relativeStart be ToInteger(start)". If you look at the algorithm for the abstract operation ToInteger(), which in turn uses ToNumber(), you'll see that it ends up converting undefined to 0.
Still, in my own code I would always say .slice(0), not .slice() - to me it seems neater.
array.slice() = array shallow copy and is a shorter form of array.slice()
Is there any reason for doing this, or is the author just making the code more complicated than it should be?
Yes there may be a reason in the following cases (for which we do not have a clue, on whether they apply, in the provided code):
checkVal() or getBufferElement() modify the content of the arrays passed to them (as second and first argument respectively). In this case the code author wants to prevent the global variable _buffer's content from being modified when calling unmaskedvalue().
The function passed to $.map runs asynchronously. In this case the code author wants to make sure that the passed callback will access the array content as it was during unmaskedvalue() execution (e.g. Another event handler could modify _buffer content after unmaskedvalue() execution and before $.map's callback execution).
If none of the above is the case then, yes, the code would equally work without using .slice(). In this case maybe the code author wants to play safe and avoid bugs from future code changes that would result in unforeseen _buffer content modifications.
Note:
When saying: "prevent the global variable _buffer's content from being modified" it means to achieve the following:
_buffer[0].someProp = "new value" would reflect in the copied array.
_buffer[0] = "new value" would not reflect in the copied array.
(For preventing changes also in the first bullet above, array deep clone can be used, but this is out of the discussed context)
Note 2:
In ES6
var buffer = _buffer.slice();
can also be written as
var buffer = [..._buffer];

DOJO difference between instantiation and using source

I am new to DOJO and trying to figure out the difference between these two uses of the seemingly two things.
dndController: new dijit.tree.dndSource("dijit.tree.dndSource",{copyOnly:true})
and
dndController: "dijit.tree.dndSource"
The second one works, but when I use the first one, it gives me an error when loading my tree. It says type node is undefined. The reason I want to use the first one though is because I want to set copyOnly to true.
Any answers appreciated it.
That parameter expects a constructor function instead of the object you passed. Perhaps the following would work:
dndController: function(arg, params){
return new dijit.tree.dndSource(
arg, // don't mess up with the first parameter
dojo.mixin({}, params, {copyOnly:true}))
//create a copy of the params object, but set copyOnly to true
}
Some explanation:
I actually don't know anything about drag-and-drop on trees. All I did was look at the Tree source code (its at dijit/Tree.js or something like that) to find out where dndController is used. From that point I could find out that is was supposed to be a function that can receive these two parameters (or a string representing the path to such a function...). The actual dijit.tree.dndSource function that is used I just copied from your question statement, hoping it would work.
The dojo.mixin function mixes in all the objects in its 2nd, 3rd, ... arguments into the first argument. By using a new, empty, object as the "receiving" object we have a neat way to make a shallow copy of params, settting copyOnly without modifying the original params object.

Categories

Resources