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

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.

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.

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.

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

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));
}

Javascript: How to access a public variable in the same class?

I recently started programming JavaScript and thought everything would be good...
Well today I faced a problem I can't solve on my own.
My tutorial/ learning project has a class called model. In this class there are several private and one public variable. This variable is of type CustomEvent:
function Model(){
/**
* Array in which the questions are stored
*/
var questions=new Array();
var db;
var valuesSplit="*";
var tableName="quests";
this.myEvent=new CustomEvent("my event");
So as you can see "myEvent" is public and can be called from outside. In this case it is an event which can be subscribed (this is done outside this class by other objects that want to listen) and it can be fired (this is done in the same class). And this is my problem.
How can I access myEvent within the model class?
I tried:
this.myEvent.fire()
and:
myEvent.fire()
But I always get "myEvent is not defined".
Probably the first thing to say is: JavaScript doesn't have classes. The sooner you stop thinking of "JavaScript classes," the better off you'll be. :-) JavaScript has OOP, but not the kind with classes. Your Model function is called a constructor function.
You can access myEvent from any code that has a reference to the object created by new Model, which includes code in your constructor (via this — e.g., the way you're setting it up) and any function called with this referring to that object (or, of course, "externally" via someObjReference.myEvent).
So probably this.myEvent.fire() is what you want, but the code you're calling it from doesn't have the right this value. That's because in JavaScript, this is controlled entirely by how a function is called, not where the function is defined as it is in some other languages. See my blog articles Mythical methods and You must remember this for more details, but I've done a somewhat truncated discussion below.
Here's an example of a fairly standard way to set up a constructor function with useful methods that all instances share:
function Foo() {
this.myEvent = new CustomEvent("my event");
}
Foo.prototype.bar = function() {
this.myEvent.fire();
};
// Usage:
var f = new Foo();
f.bar(); // Fires the event indirectly, via the code in `bar`
f.myEvent.fire(); // Fires it directly
Note that that only works if bar is called with this referring to an object with a myEvent property. It's easy to call bar with this set to something else entirely:
document.getElementById("someID").onclick = f.bar;
When the click occurs, the bar function gets called, but this does not refer to an object created via Model. (It will refer to the element with the id "someID" instead.) And so this line in bar
this.myEvent.fire();
...will fail.
If you're used to class-based languages, you can see how this is totally different from, say, Java, C#, or C++. In those langauges, this inside bar will always refer to an object created via new Model. Not so JavaScript, which is both awkward and powerful.
This flexibility of functions (not being bound to any particular object) is one of the biggest things to get used to, and take advantage of, in JavaScript. The other is how functions are closures, which is powerful but not complicated.
So if this is set by how a function is called, how do you do that? There are two ways:
Call the function by referencing it from an object property in the same expression as the call. That's an awkward way of saying do this:
var f = new Foo();
f.bar(); // <== The key bit
f["bar"](); // <== Also works
The expression f.bar() does two things, which interact: The first thing it does is retrieve the property bar of the object referenced by f, and get that property's value (which is a function reference). Then it calls that function (because of the ()). The way JavaScript works, because you did those two things in the same overall expression, the interpreter sets this to f during the call to bar for you. But note this key distinction:
var f = new Foo();
var b = f.bar;
b(); // <== Different!
Now when the bar function gets called, this will not be set to f (it'll be set to the global object, which is window on browsers), because we've separated the property retrieval from the function call.
Alternately, you can use the built-in features of JavaScript function objects, their call and apply functions. call and apply do exactly the same thing, the only difference between them is how you supply the arguments for the function. Example:
var f = new Foo();
f.bar(1, 2): // <== Calls `bar` with `this` === `f` and passing in
// the arguments 1 and 2
var b = f.bar;
b.call(f, 1, 2); // <== Does the same thing as f.bar(1, 2)
var args = [1, 2];
b.apply(f, args); // <== Does the same thing as f.bar(1, 2)
E.g., call and apply allow you to set what this should be explicitly when you call the function. The only difference between them is that call accepts the arguments to give the function as further arguments to call, and apply accepts them as an array.
If you want to use myEvent in a non public function in your Model than you have to create another reference to the myEvent which isn't using the this reference of your Model. Because the this in another function is something else than in your Model function. The easiest way to bypass this problem is if you define a new variable in your Model:
var that = this;
Then you can call your myEvent like:
that.myEvent
The myEvent member should be visible both in the inner & outer scope of the object :
function Model(){
this.myEvent = 'some value';
this.canAccessEvent = function(){
return 'myEvent' in this;
}
}
var m = new Model();
// access from outside :
alert(m.myEvent);
// access from inside :
alert('Model can access the even? ' + m.canAccessEvent());
However, it is very possible that your new CustomEvent function doesn't exist or does not return a valid object making your myEvent variable to be undefined. I suggest you attribute some other value to the myEvent property and see if it is defined. If it is defined, then the problem lies in your CustomEvent function.

In javascript functions, can you set this.function = function?

I have run into this jquery plugin and i quite understand how this works:
$.functionone = function(){
function setOptions(newOptions){
...
}
this.setOptions = setOptions;
}
What i dont understand is what does this actually do? this.setOptions = setOptions can you call a function without parenthesis? What is the relationship between this.setOptions and setOptions by itself?
Functions in JavaScript are objects like (nearly) everything else. When you do this:
this.setOptions = setOptions;
you're not calling the setOptions function, you're just assigning a reference to the function to a property, exactly like setting a property to any other object, like this:
var dt;
dt = new Date();
this.today = dt;
With functions, you'd do this so you can later call the function via the property (which sets up the this value to be the object the property's on, which is handy). It's a bit clearer what's going on if you use a different name for the property than for the function:
function functionName() { ... } // Declares the function
this.propertyName = functionName; // Sets the property
functionName(); // Calls the function (with `this` = the global object ["window", on browsers])
this.propertyName(); // Also calls the function (but with `this` = the object the property's on)
The pattern you identified, declaring a function and then separately setting a reference to it on an object, is frequently used to make sure the resulting function has a name. You can create a function and bind it to a property like this:
this.setOptions = function() {
...
};
...but then the function doesn't have a name (the property does, but not the function), which can be an issue when you're trying to debug because debuggers show you the names of functions in various contexts (call stacks, for instance). If a lot of your functions don't have names, even though the properties referring to them do, it makes debugging difficult. More about anonymous vs. named functions here. (There's also a difference in terms of when the function is instantiated, but going into it here would just complicate things.)
You'd think you could combine things, like this:
this.setOptions = function setOptions() { // <=== DON'T DO THIS
...
};
...but although that mostly works, it triggers a bug in Internet Explorer / JScript (it creates two different functions for that code, which is at best a memory waste and at worst a very subtle and time-wasting problem, as it was in this question).
The function setOptions is only called if you add parenthesis: setOptions(). If you do not add parenthesis, you have a reference to a function. This is just like a normal variable, only it contains a function reference instead of some other value.
If you set this.setOptions = setOptions, you make a function setOptions on the this object, which points to the same function as setOptions. That is, if you call it using this.setOptions(), the referenced function will be called.

Categories

Resources