Using bind to hold a function's arguments in the "this" scope - javascript

I'm playing around with bind, and the following works:
webSQL.InsertTransaction = function(qry,CurrentRow) {
var local = {};
// Clone the webSQL.Insert function and add 2 parameters:
local.InsertTransaction = webSQL.Insert.bind(this,qry,CurrentRow);
// Call webSQL.Insert(qry,CurrentRow,Transaction)
dbo.transaction(local.InsertTransaction);
}
webSQL.Insert = function(qry,CurrentRow,Transaction) {}
I'd like to simplify it even more. Can I somehow not have to specify the 2 variables that are in the arguments scope, but instead do something like:
local.InsertTransaction = webSQL.Insert.bind(webSQL.InsertTransaction)
maybe. My thinking is that then webSQL.Insert can reference qry and CurrentRow from it's "this.arguments" thingy.

I'm not sure why you were using the object assigned to the local variable in the first place.
All you were doing was giving it a function, and then taking that function right back out. Why not skip that step?
webSQL.InsertTransaction = function(qry,CurrentRow) {
dbo.transaction(webSQL.Insert.bind(this,qry,CurrentRow));
}

Related

How to use in-scope variables in functions passed as parameter

This is probably a basic question, and I am aware that there have been some similar questions around here, but still I did not find an answer. Please consider the following code:
function Outer(inner2) {
var x = 5;
this.inner1 = function() {return (x);}
this.inner2 = inner2.bind(this);
}
var outer = new Outer(function() {return (x);});
alert(outer.inner1()); // works
alert(outer.inner2()); // does not work
If I would replace the second line by this.x = 5;, the second alert would work. So I guess the problem is that x when declared with var is not part of this, so that bind will have no effect.
Is there any way to make this work without using this.x?
Is there any way to make this work without using this.x?
No.
Btw, you probably don't even need to use bind, just calling inner2 as a method on the object would suffice when both the constructor and the method use this.x.
If you don't want to make x a property of the object, but keep it as a local variable, the usual strategy would be to pass it to the callback as an argument, not trying to somehow make it available in its scope implicitly:
function Outer(callback) {
var x = 5;
this.inner1 = function() { return x; };
this.inner2 = function() { return callback(x); };
// ^^^
}
var outer = new Outer(function(y) { return y; });
// ^ ^
alert(outer.inner1()); // works
alert(outer.inner2()); // works
I think you need clarification on what the word "this" is referring to.
"this" is not pointing to the function "Outer."
When you invoke a constructor function with the "new" keyword, a few things happen.
The constructor function returns an object.
The "this" variable is changed, so that it is set to point to that object that is returned.
(Also, the .proto of the object returned is set to the .prototype of the constructor function, but that step is not relevant here).
So, you are binding the callback function to the object that you are returning from the constructor function, not the constructor function itself.
Thus, the callback function is bound to outer (with a lower-case), not outer (with an upper-case).
Also, when you bind, you are not binding to the scope of a function. X is not assigned to any property. I think you only can bind to an object and access its properties with this.a etc.
The x in the first function worked because its value was assigned in the scope of the function.
I found an, albeit ugly, solution:
function Outer(inner2) {
var x = 5;
this.inner1 = function() {return (x);}
eval('this.inner2 = ' + inner2.toString());
}
This works and shows my point: the parameter inner2 is just a prescription of how this.inner2 should look like; it is never invoked itself.
Let me know, if you have a neater solution than this.

Is it possible in Javascript to create an external closure?

Normally, to create a closure, you create it inside another function, and it gets the scope of its parent:
var parent = function(){
var a = "works!";
var subfunction(){
console.log(a); // "works!"
}
subfunction();
}
I'm trying to figure out a way to emulate this closure behavior with a function that is defined outside of the parent function. I know this is possible using parameters:
var parent = function(){
var a = "hello";
subfunction(a);
}
var subfunction(a){
console.log(a); // works, but because it's a param
}
I'm trying to figure out if there's a way to do it without having to explicitly set all parameters. I was initially thinking I'd be able to pass the functions local scope object as a parameter
var parent = function(){
var a = "hello";
subfunction(localScope);
}
var subfunction(localScope){
console.log(localScope.a); // not going to work this way
}
... but I've since discovered that it's impossible to get a reference to a function's scope. Is there some other way to emulate a closure outside of the actual scope of a function?
No, closures in JS are always lexical (i.e. referring to their parent scope).
If you want to create a closure with an explicitly set environment, you may of course use a helper function for that:
function unrelated() {
var closure = makeClosure("hello");
closure();
}
unrelated();
function makeClosure(a) {
return function() { // closes only over `a` and nothing else
console.log(a);
}
}
That's as close a you will get to an "external closure". Notice you can only pass values to makeClosure, not references to local variables. Of course you could make objects and pass the reference to them around, and with with (not recommended!) you could even make them look like variables.

javascript - help me understand this structure (lexical scoping)

Below is simplification of some code I am trying to understand.
What are we trying to do in this javascript fragment? It seems we are creating object(?) called myCompany if not already created, then adding child object myProject to myCompany.
Then creating a local variable withinmyCompany.myProject and another local to function myCompany.myProject.myfunction. The () at the end make it execute immediately. And we are doing this to keep localVariable_1 out of global space?
var myCompany= myCompany || {};
if (!myCompany.myProject) {
myCompany.myProject = {};
}
myCompany.myProject = function () {
var localVariable_1;
function myFunction(){
var anotherlocalVariable;
// .. do some stuff
}
}();
The first line checks if the object exists, if not use shorthand definition {} to create an Object. || compares. If argument one is null set argument two.
The if on the next line checks if the property myProject isn't set on the object. ! is the operator. If myCompany.myProject returns undefined this if clause returns true. When true create object as property myProject.
Third part: myProject gets replaced by a function object. This function is defined between { and }, but is immediately called upon by the () behind the function declaration.
localvariable_1 will never be in the global scope since it has the var statement. Binding it to the scope of myCompany.myProject function. Maybe this function is directly called to set up some initial values, but wrap them in a function that could be reused to change the values at another moment.
One piece at a time...
var myCompany= myCompany || {};
if myCompany exists you set it to it, otherwise you create an empty object and set myCompany to an empty object.
NOTE: if myCompany already exists you have no indicator of what it is
if (!myCompany.myProject) {
myCompany.myProject = {};
}
Now that you know myCompany is an object you verify it has a project property on it. if not you set myProject to an empty object.
NOTE: you have tested nothing about myProject so again there is no indicator of what it is
myCompany.myProject = function () {
var localVariable_1;
function myFunction(){
var anotherlocalVariable;
// .. do some stuff
}
}();
Here you are assigning myCompany.myProject. Notice at the bottom the () before the ; That makes this function get executed immediately. Inside of the function you are creating another function that currently isn't doing anything. Where you aren't returning from the function I think it will set myProject to undefined.
You may already know what an immediate function is but if not it is basically a function that is called right away. It is also standard to wrap it in a () so that it is easier to read for example
var someFunction = (function () {
/*whatever*/
} ());
You said this was simplified from the original so I am guessing you removed an important part of the code that actually does things but the confusion is probably due to the JavaScript's way of scoping. It uses what is called Lexical scoping. You can think of it as scoping by functions.
Another thing that may be tripping you up is how JavaScript uses truthy evaluation for logical comparisons.
The last thing to mention that might be confusing the way you read the code is javascript's hoisting.
Hopefully that helps or at least points you to a few things you can look into to figure out the parts you don't exactly understand.
Sorry I just hate writing in comments lol.
If you are trying to help prevent your global scope from getting polluted then you might want to use objects and a something similar to what you are doing. Depending on how crazy you want to get you could look into Prototypical Inheritance.
A common pattern is to do something like this
var company = (function() {
var name;
var getName = function() {
return name;
};
var setName = function(n) {
name = n;
};
return {
getName : getName,
setName : setName
}
}())
Now you can do company.setName("yoda") or whatever.
This will give you a basic getter and setter where no one can change the companies name without going through your getter and setter and it also doesn't pollute the global scope. You can have whatever you want on company this way and you also encapsulate the data within the object.
Notice how var company = a function that is called immediately which returns an object that has whatever you want to encapsulate on it.
Is that what you are talking about?

Why Does JavaScript Automatically Allow My Function To Take An Extra Argument?

I am not understanding JavaScript scoping and inheritance correctly. I clearly defined a function to take 1 argument (and I understand that this is optional due to how JavaScript handles arguments) but it looks like I need an extra argument to make the scoping work. Why is this?
ShapeRenderable.prototype = new Renderable();
function ShapeRenderable()
{
this._line_join = 'round';
this._line_cap = 'round';
.
.
}
ShapeRenderable.prototype.setFillColor = function (fill_style)
{
if (fill_style)
{
this._fill_style = fill_style;
this.initialAlpha = fill_style._alpha;
}
else
{
this._fill_style = new RGBA(0,0,0,1.0);
}
};
SelectionCube.prototype = new ShapeRenderable();
function SelectionCube()
{
var self = this; // So we can access public methods and members from within
// private ones.
self._visible = true;
self._scale = 1;
self._stroke_style = new RGBA(0,0,0,.1); // Lines solid black
self._line_width = 7.0; // 1
var platonicRenderable = new PlatonicRenderable(this);
platonicRenderable.createCube();
// surfaces mostly transparent white
ShapeRenderable.prototype.setFillColor.call(this, new RGBA(255,255,255,1));
// Why do I have to pass "this" to get the correct scope during
// execution of the above? If "this" isn't passed, it looks like JavaScript
// is scoping this for the parent, instead of for the child.
//
// This is the correct behavior. My cube is now white.
}
If I just call:
ShapeRenderable.prototype.setFillColor.call(new RGBA(255,255,255,1));
Then my renderable is black (which is incorrect) and it looks like this._fill_style is never set correctly for my SelectionCube. Why is this? Is there some secret JavaScript optional (first) parameter which tells the function what scope to use during execution? I was having the above issue, and I read about passing this so that the class reference will still point to the child but I never understood why.
Here's what it looks like for the two cases:
Broken - Not Updating "this" correctly
Works - Updating "this" correctly
You're using .call incorrectly. The correct syntax for call is
fun.call(thisArg[, arg1[, arg2[, ...]]])
See the docs.
The first parameter is the "scope" or the this object within the function. Subsequent arguments are passed to your function's parameters.
However in this situation it's best to use #elclanrs suggestion in your comments.

Javascript closure & "that" instead of "this" in a specific example

I know this subject had been dealt a lot here, but I saw this specific example on the Pluralsight JS design pattern course, and I'll be glad for your help understanding the closure there.
This is the example:
var Calc = function(start) {
var that = this;
this.add = function(x) {
start = start + x;
return that;
};
this.multiply = function(x) {
start = start * x;
return that;
};
this.equals = function(callback) {
callback(start);
return that;
};
}
new Calc(0)
.add(1)
.add(2)
.multiply(3)
.equals(function(result){
console.log(result); // returns 9
});
Here's the JSFiddle link: http://jsfiddle.net/3yJ8Y/5/
I'll be VERY glad for:
Understanding the "that" use. Why do we need it in this specific
example? it does the same with "this". Can you pls give examples and explain when do we need to do "var that = this"?
Understanding this way of creating functions from an object. why do we have to use "this" and then .functionName? like this.add = ...
A detailed and extensive explanation for this very specific closure example.
Thank you so much!
start becomes a global variable of the Calc object
Each method of the Calc object (add, multiple, equals) references that same global variable
new Calc(0) // <- sets start to 0
.add(1) // calls add() <- sets start to 1
.add(2) // calls add() <- sets start to 3
.multiply(3) // calls multiple() <- sets start to 9
.equals(function(result){
console.log(result); // returns 9
});
Thanks to #elclanrs for reminding me of things I had internalized and forgotten...
That
The important thing here is that that... is unnecessary.
I'll quote an article that #elclanrs linked in his comment on the above post:
Scope In Javascript
JavaScript establishes an execution context for the function call, setting this to the object referenced by whatever came before the last ”.”
Because each method is called with the outer Calc before it's dot, the this value inside that method is assigned as the outer object.
The outer object, in turn, is its own brand new, self-contained scope because it was created with the new keyword:
When new[Calc]() is executed, a completely new object is created transparently in the background. [Calc] is called, and its this keyword is set to reference that new object.
(Scope in Javascript, again, with my edits in brackets).
Now you might be wondering, "How is this:
.add(1)
.add(2)
.multiply(3)
... keeping the right scope? You said that whatever is before the . is passed in as the this variable in this situation!?"
Absolutely true, and in this situation, each method is returning this, which allows method chaining. (They're actually returning that, but we already determined that was an unnecessary variable in this context).
Why use that
First of all, let me say I prefer var self = this over var that = this but there are arguments either way.
Let's arbitrarily modify the object to have a method that looks like this:
this.getInternalThis = function(){
var internalThis = function(){
console.log( this );
}
}
First of all, let's get this out of the way: this example is stupid, but you'll see things like this - a function defined in other scopes - all the time.
Here are the important things to notice:
It's called by name, and nothing more (no prefixed . notation, for example)
... that's it!
When a function is called this way, the engine has to figure out something to assign this as in the scope of the function. It defaults to window.
If you were to run this code, you would get Window in the console.
Now, what if we wanted this inside that internal function call to be the calling value of this?
This situation is where you need a that variable. We can modify the function to look like:
this.getInternalThis = function(){
var that = this,
internalThis = function(){
console.log( that );
};
}
Now when you run this method, you get the value of the calling object in the console.
In my case it was Object { add=function(), multiply=function(), equals=function(), getInternalThis=function()}.
Sometimes, that's what you need or expect, so that's why you would use a var that = this declaration.
Using this. to define a method
As I mentioned earlier:
Because each method is called with the outer Calc before it's dot, the this value inside that method is assigned as the outer object.
Remember that this in the scope of Calc() is a reference to the new Calc object, so each method is being given the Calc object as the value of this (remember, it's before the .!) when they enter their new scope from that context.
Hopefully this gives you a little info on how JavaScript scopes and the assignment of this works.

Categories

Resources