this != this in javascript (well, sometimes....) - javascript

Example 1
var Reptile = function () {
var reptile = this;
this.showBla = function() {
alert(reptile.bla);
}
}
var turtle = new Reptile();
turtle.bla = 'whatever';
turtle.showBla();
Example 2
var Reptile = function () {
this.showBla = function() {
alert(this.bla);
}
}
var turtle = new Reptile();
turtle.bla = 'whatever';
turtle.showBla();
Is example 1 legit? As it sometimes seems to screw things over to define "this" directly in the constructor...?!?

Yes, it is legit and is useful in cases where you may need to define a function inside a function that may be invoked in a way there "this" will pointer to something else. Books recommend naming this variable var that = this;

Example 1 is a common pattern for maintaining the reference to the current instance. In a callback situation, like:
setTimeout(turtle.showBla, 0);
Example 1's var reptile... saves the this reference and will show 'whatever'. Example 2 will show undefined, unless you manually assign scope on the calling side (e.g., in jQuery):
setTimeout($.proxy(turtle.showBla, turtle), 0);

Related

Set Javascript variable in a class from outside

I have a library which has defined a class as this. I would like to call getMe() function outside class A with my own me.
var me;
var A = function(_me){
me = _me;
}
A.prototype.getMe = function(){
me();
}
I have class B where I call it like
A.prototype.getMe.call(this) but this would throw an error as me is not defined. How can I pass me into this ? I would like to make minimum changes to getMe function.
The only way to do this is, I guess to use an if .
A.prototype.getMe = function(){
if(!me){
me = this.myMe
}
me();
}
So I did A.prototype.getMe.call({myMe: myMe}, args) but would it define the variable in global space ?
You can't reasonably do this, not least because A is fundamentally broken (see below).
Whether you can do it at all depends entirely on where the A code is: If it's at global scope, you can do what you want but shouldn't. If it isn't at global scope, you can only do it from code within the scope where me is declared (or a scope within it).
If it's at global scope, you'd do it like this (but don't :-) ):
// The "A" Code
var me;
var A = function(_me){
me = _me;
}
A.prototype.getMe = function(){
me();
}
// Your code using it
new A(); // Create `A.prototype.getMe`, because unless
// `A` is called at least once, it doesn't exist
var myMe = function() {
console.log("myMe called");
};
me = myMe; // Set the global `me`
A.prototype.getMe(); "myMe called"
The only way to do this is, I guess to use an if .
if(!me){
me = this.myMe
}
So I did A.prototype.getMe.call({myMe: myMe}, args) but would it define the variable in global space ?
Yes, it would. That's what me = this.myMe does.
From that observation, it sounds like you can modify A's code. If so, fix it so that it doesn't define a prototype function in terms of a global variable. Perhaps isolate the code from the function into a function that doesn't expect to be called on an instance and pass in me as a parameter.
I am working on an existing library to make a small change. So I can only change inside getMe function definition. And I cant change var me definition.
In that case, you can add a new optional parameter at the end, and use that if provided and me if not provide:
A.prototype.getMe = function(myMe){
var meToCall = myMe || me;
meToCall();
};
Live Example:
// The "A" Code
var me;
var A = function(_me){
me = _me;
}
A.prototype.getMe = function(myMe){
var meToCall = myMe || me;
meToCall();
}
// Your code using it
A.prototype.getMe(function() {
console.log("My me!");
});
And, separately, A is fundamentally broken if it's really as shown (barring an extremely specific use-case). Having constructor code set a global (global at least to A's code) that's then used by a prototype function is a huge design and maintenance red flag.
Consider the cross-talk horror:
// The "A" Code
var me;
var A = function(_me){
me = _me;
}
A.prototype.getMe = function(){
me();
}
// Using it
var a1 = new A(function() {
console.log("me1");
});
a1.getMe(); // "me1" -- so far so good
var a2 = new A(function() {
console.log("me2");
});
a2.getMe(); // "me2" -- yup, still fine
a1.getMe(); // "me2" -- what the...?!?!?!!

JavaScript: that vs this

I am trying to understand better the use of that and this in JavaScript. I am following Douglas Crockford's tutorial here: http://javascript.crockford.com/private.html
but I am confused regarding a couple of things. I have given an example below, and I would like to know if I am making a correct use of them:
function ObjectC()
{
//...
}
function ObjectA(givenB)
{
ObjectC.call(this); //is the use of this correct here or do we need that?
var aa = givenB;
var that = this;
function myA ()
{
that.getA(); //is the use of that correct or do we need this?
}
this.getA = function() //is the use of this correct?
{
console.log("ObjectA");
};
}
function ObjectB()
{
var that = this;
var bb = new ObjectA(that); //is the use of that correct or do we need this?
this.getB = function()
{
return bb;
};
that.getB(); //is the use of that correct or do we need this?
}
Note this is just an example.
this in JavaScript always refers to current object, method of which was called. But sometimes you need to access this of your object in deeper. For example, in callbacks. Like so:
function MyClass() {
this.a = 10;
this.do = function() {
http.get('blablabla', function(data) {
this.a = data.new_a;
});
};
}
It will not work, because this in callback may refer to http, to some dom element or just window(which is really common). So, it is common solution to define self or that, an alias for this or your object, so you can refer it anywhere inside.
function MyClass() {
var self = this;
this.a = 10;
this.do = function() {
http.get('blablabla', function(data) {
self.a = data.new_a;
});
};
}
This should give you vision why it is used and how it should be used.
There is no other reasons(currect me if I'm wrong) to create special variable, you can use this to send your object to other objects and do things, many assignments, such logic, wow...
ObjectC.call(this); //is the use of this correct here or do we need that?
The first thing you need to understand is how the this keyword works. It's value depends on how the function/method/constructor is called.
In this case, function ObjectA is a constructor, so you can just use this inside the code of it. In fact, with var that = this; you declare them to be absolutely identical (unless you use that before assigning to it).
function myA() {
that.getA(); //is the use of that correct or do we need this?
}
Again, it depends on how the function is called - which you unfortunately have not show us. If if was a method of the instance, this would have been fine; but but it seems you will need to use that.
this.getA = function() //is the use of this correct?
As stated above, using that would not make any difference.
var bb = new ObjectA(that) //is the use of that correct or do we need this?
var that = this;
that is undefined when it is used here. And it would be supposed to have the same value as this anyway. Better use this.
that.getB(); //is the use of that correct or do we need this?
Again, both have the same effect. But since you don't need that, you should just use this.
Everything is correct except for :
function ObjectB()
{
var bb = new ObjectA(that) //this is wrong
var that = this;
this.getB = function()
{
return bb;
};
that.getB();
}
You are missing ; and that isn't declare.
You need that (in your case, this is the variable name you use) when you want to use this in another scope :
function ObjectB()
{
var that = this;
// here 'this' is good
function()
{
// Here 'this' doesn't refer to the 'this' you use in function ObjectB()
// It's not the same scope
// You'll need to use 'that' (any variable from the ObjectB function that refers to 'this')
};
// Here 'that' = 'this', so there is no difference in using one or another
}
What "that" is in this context is simply a variable that is equal to "this". That means saying "that" is exactly the same as saying "this", which makes in unnecessarily complicating.
This code:
var that=this;
that.getA();
Will yield the same result as this code:
this.getA();
Having a variable to represent "this" just complicates things when you can just say "this".

How to access properties of object created and returned from a function

var steve = function() {
var bob = {};
bob.WayCoolTest = function () {console.log('done deal');};
return bob;
}
window["steve"]["WayCoolTest"]
running this in chrome console, my test app, anywhere results with undefined. I do not understand why, can someone explain why this does not work and help me fix it. Thank you very much!!
Using window is usually redundant - let me demonstrate:
var foo = '123';
alert(foo); //123
alert(window.foo) //123
alert(window['foo']) //123
It is evident which is more convenient. There is a circumstance in which the use of window makes sense, but that circumstance is almost always because of poor architecture. Using window allows us to access a variable global variable - funny wording :) This should clear it up:
var foo = '123';
var bar = 'abc';
var prop;
if (blah) { //some condition here
prop = 'foo';
}
else {
prop = 'bar';
}
Now...how can we use prop to get the value of a corresponding variable?
console.log(window[prop]); //123 or abc - bracket notation lets us use variable property names
This sort of thing is very common within objects, but not with window. The reason is that we should be avoiding global variables (properties of window) as much as possible. Therefore, any logic that needs a variable property name should be inside of an object, dealing with objects - NOT window. Now window can be out of the picture.
It is usually bad practice to create functions inside of other functions. That would mean that each time you call function A, you recreate function B. Most of the time, people do that because they don't know better, not because they need to.
It appears to me that you intended to give steve a property called WayCoolTest, both being functions. That can be done.
var steve = function() {
console.log("I'm Steve!");
}
steve.WayCoolTest = function() {
console.log("I'm a Way Cool Test!");
}
steve(); //I'm Steve!
steve.WayCoolTest(); //I'm a Way Cool Test!
This works because functions are objects in javascript. Therefore, you can add properties to them.
Let's step it up!
To emphasize good practices, I'm going to wrap this example in an object testApp (it acts like a namespace..we're using that instead of window).
I will create a property of testApp called steve, which will be a function.
Rather than creating steve directly as a function, I will use an IIFE (immediately invoked function expression), which is a function that will return something to be set as steve.
Inside the IIFE, I will create the function for steve and also attach WayCoolTest to it, as demonstrated in the previous example, then that function is returned and assigned to steve.
var testApp = {
steve : (function() {
var steve = function() { //the name here doesn't matter, just being consistent, since this will be the value of the property `steve`.
console.log("I'm Steve!");
}
steve.WayCoolTest = function() {
console.log("I'm a Way Cool Test!");
}
return steve;
}());
};
testApp.steve(); //I'm Steve;
testApp.steve.WayCoolTest(); //I'm a Way Cool Test!
Now, let's consider another variation.
var testApp = {
steve : (function() {
var steve = function() { //the name here doesn't matter, just being consistent, since this will be the value of the property `steve`.
console.log("I'm Steve!");
WayCoolTest(); //Steve can use this, but nothing else can! Encapsulation.
}
var WayCoolTest = function() { //THIS PART!! No longer a property of "steve"
console.log("I'm a Way Cool Test!");
}
return steve;
}());
};
testApp.steve(); //I'm Steve! I'm a Way Cool Test
testApp.steve.WayCoolTest(); //undefined, of course
That is very useful if for example steve is a complicated function and you want to break it up into some other small functions that only steve will know about.
To complement the other answers, your code would work this way:
var steve = function() {
var bob = {};
bob.WayCoolTest = function () {console.log('done deal');};
return bob;
}
window["steve"]()["WayCoolTest"]();
or
var steve = (function() {
var bob = {};
bob.WayCoolTest = function () {console.log('done deal');};
return bob;
})();
window["steve"]["WayCoolTest"]();
or, the dirtiest way...
steve=(function() {
var bob = {};
bob.__defineGetter__("WayCoolTest", function () {console.log('done deal');});
return bob;
})();
window["steve"]["WayCoolTest"];
Assuming steve is in the global scope and you dont seem to use steve as a constructor you can use immediate function and return the new object that you have created inside of it.
var steve = (function () {
var bob = {};
bob.WayCoolTest = function () {
console.log('done deal');
};
return bob;
})();
window["steve"]["WayCoolTest"]();
If it is in a closure then you would have to either remove var for hoisting to happen so it becomes a part of window or set it to the window object as a property.
window.steve = (function () {
var bob = {};
bob.WayCoolTest = function () {
console.log('done deal');
};
return bob;
})();
If you declare using var it doesn't get associated with the global window scope. It's instead a local variable. Also bob is not a property on the steve object they way you have it set up

How to change function inside constructor in JavaScript?

I need to edit the function which locates inside of the constructor.
Example:
some.thing = function() {
this.somefn = function() { // this is the function that I need to fix
...
}
}
But function should be edited not just only for a single object (new obj = some.thing();) but also for any created objects by this constructor.
So is there any way to edit such inner-functions?
Here is a solution based on prototype:
var Something = function () {
this.f = function () {
console.log("Something");
};
};
var Old = Something;
var Something = function () {
Old.apply(this);
this.f = function () {
console.log("New");
};
};
Something.prototype = new Old();
var s = new Something();
s.f(); // prints "New"
The solutions seem just a little too obvious, so I'm wondering if the trouble is that you don't have access to the original code, and you need a more dynamic solution.
If so, one option may be to override the constructor with your own constructor, and have it call the original, and then update the object.
Original code:
some.thing = function() {
this.somefn = function() { // this is the function that I need to fix
...
}
}
Your code:
// cache a reference to the original constructor
var _thing = some.thing;
// your constructor
some.thing = function() {
// invoke the original constructor on the new object.
_thing.apply(this, arguments);
this.somefn = function() { /*your updated function*/ };
};
// maintain inheritance
some.thing.prototype = Object.create(some.thing.prototype);
// make an instance
var theThing = new some.thing();
Now you're getting the benefit of the original constructor and prototype chain, but you're injecting your own function on to the objects being created.
Only trouble may be that the original function you replaced could make special use of the original constructor's variable scope. If that's the case, there would be an issue to resolve.
It would be possible to retain and invoke the original method that you overwrote before invoking yours. Not sure if this situation calls for that or not.
I exactly know your need cause last week I passed through it. I just implemented a complete inheritance model in javascript and as far as I remember, I had a problem with overriding constructors and calling the parent class's ctor when child class is initializing.
So I just solved the problem with modifing some points in my design and it's now working like a charm! (something like C# but in Javascript)
By the way, I don't suggest you to change a method contents this way, but here is a way to do that (I myself did not do that this way and AGIAIN I DO NOT RECOMMEND IT. THERE ARE MANY OTHER WAYS, BUT THIS IS THE EASIEST):
var test = function() { /*InjectionPlace*/ };
eval("var newTest = " + test.toString().replace(
"/*InjectionPlace*/",
"var i = 10; alert(i);"
));
test();
newTest();
Cheers

how to get a reference to the defining 'class' inside an inner method in JavaScript?

I have the following JS code:
var Item = function ()
{
this.property = '';
this.myfunction = function ()
{
var value = this.property;
};
};
however, this does not point to the defining class so value doesn't get anything.
how do I access this.property from inside my function?
You need to create a closure which captures the value of parent scope's this:
var Item = function ()
{
this.property = '';
var self = this;
this.myfunction = function ()
{
var value = self.property;
};
};
Update: As others have pointed out, this closure is not needed when Item is used as a constructor (new Item()). Noting it here for future reference.
just create an alias for this. It will get closure'd.
var Item = function ()
{
this.property = '';
var self = this;
this.myfunction = function ()
{
var value = self.property;
};
};
Your code works as is if you call Item() as a constructor.
var item = new Item();
item.property = "the property";
item.myfunction(); // value = "the property"
this changes depending on the context. The context being how a function was invoked, not how it was defined, but how it was called.
Besides that, you seem to be mixing up two patterns here. I'm sure you meant something like:
var Item = function() {
this.property = '';
};
Item.prototype.myfunction = function() {
var value = this.property;
};
Instead you kind of mixed a closure pattern with prototypal, which doesn't seem very useful there. Closure is good for hiding members, allowing for true private members, but here you're exposing the property anyway. There's no reason not to stick that function on the prototype.
Do yourself a favor and ignore any concepts you have of more traditional OO, they won't do you any good here. Prototypal isn't nearly the same thing.

Categories