Maintaining Object state in javascript DOJO - javascript

I have the following code to call an function on each button in a page.
dojo.query('.btn').forEach(function(item){
Obj = new MyClass(item); // class calls the ajax request on error of each btn click I have to handle some functionality in below function showError
dojo.connect(Obj, 'showError', dojo.hitch(Obj, function(errors){
console.log(Obj + 'came');
}));
Here I tried using dojo.hitch to maintain state of each object Obj, But it is not maintaining.Only first Obj is firing.For second Button also, the first Obj is firing.Is there anything I am missing here.

Obj is declared as a global variable. Try putting a var in front of it. For example:
var Obj = new MyClass(item);
If you don't provide the var, it will create a globally accessible variable called Obj. This means that each time you loop, you refer to the same global variable. The result of this is that each one is connected to the same Obj (and that's why both buttons are connected to the same object).
Also, read this question on StackOverflow to get a more detailed view about declaring variables and the global scope.

Related

How to manually destroy an object in javascript?

Consider the below code,
function destroyer(obj){
obj = undefined;
}
abcObj = {
a:1,
b:2
}
destroyer(abcObj);
As far as I understand, all I can do is throw the object out of scope and the GC will clean it when it sees fit. But the above code does not throw the object out of scope.
How to force an object out of scope?
Reason for wanting to do so: The thing I wanted to achieve is a class having a static method destroy to destroy the instances of same class. Is that possible in javascript? Or is it that I can't force the cleanup. A cleanup method would be great since, the lib I'm working with spawns a lot of instances like 200 to 300.
You have to modify all the variables pointing to it.
abcObj = null;
You can't use a function to do it because that would copy the value to a new variable and leave the original untouched.
This is probably pointless as you are unlikely to be creating a significant number of objects without them falling out of scope naturally. 99.9% of the time you can just focus on writing code which does what you need it to do and let the JS engine worry about garbage collection in its own time.
Since it's defined globally just destroy it directly :
function destroyer(){
abcObj = undefined;
}
abcObj = {
a:1,
b:2
}
console.log(abcObj);
destroyer();
console.log(abcObj);
There is delete in JavaScript, but it does not delete objects, it deletes properties from objects. For your particular use case it could be used:
function destroyer(name){
delete window[name];
}
test="hello";
console.log(test);
console.log("before destroy");
destroyer('test');
console.log("after destroy");
console.log(test);
It works because you have a global variable, and "global" scope is actually "window" in the browser.
However in the general case the most you could do is to explicitly put your objects into some container object, and then you can remove them from there. It does not worth the effort IMHO.
EDIT: actually it does not work as a code snippet here, because it has its own "global-ish" scope, which is not window. But you can test it in the developer console of a browser.
EDIT2: I was wrong, it works here too, just I got confused because of the lengthy error message. Added log-lines before and after the destroyer-call.
You could pass your variable in an object, as a key, and pass that object to your destroyer function. That way, your function could use the object's first key to retrieve the global variable's name, and then delete it in the window object.
Please note this will only work for global variables.
// retrieves the first key of the object passed as parameter
function getFirstKeyName(someObject){
return Object.keys(someObject)[0];
}
// destroy a global variable by its name
function destroyGlobalVariable(withinAnObject){
// retrieve the variable's name
var globalVarName = getFirstKeyName(withinAnObject);
console.log("Deleting global variable " + globalVarName);
// use delete, assign undefined or null to window[globalVarName];
delete window[globalVarName];
}
abcObj = {
a:1,
b:2
}
// abcObj should be defined :
console.log(abcObj);
// pass your variable name into an object, as a key
destroyGlobalVariable({abcObj});
// abcObj should not be defined now :
console.log(abcObj);

Javascript hide the context

What's the best way for a method to call another method and pass the arguments in not-by-reference fashion?
i.e.
function main() {
let context = {};
// Pass context to someOtherFunction
// Such that console.log(context) in this function does not show `{whatever: true}`
}
function someOtherFunc(context) {
context.whatever = true;
}
I realize I can clone the context and pass that. But I was wondering if there was another way to do this, maybe using anonymous function wrap?
Okay, let's break this down a bit
const context = {x: true};
Above, you create an object (named context) in the global scope.
function(x) {
"use strict";
x.y = true;
}
You create an anonymous function that takes a reference to an object, and adds a new property y to that object
(/*...*/)(context);
You wrapped the above function into an IIFE so it immediately executes. For the parameter, you supplied a reference to the global context object, which is referenced by x inside the IIFE.
Objects are passed around by reference. Passing context in to the function doesn't create a new object x that is a copy of the context, it creates a new reference x that references the same object that context references.
If you need to actually copy the provided object into a new object, you need to do that yourself. As mentioned above, one mechanism is to stringify the object into JSON and then parse the JSON back to a new object. There are others depending on what you need to accomplish.
This isn't even a scope or context question at all - it's passing a reference to an object in to a function. Even if your IIFE had no way whatsoever of directly accessing the context variable, once you pass a reference to that object as an input to the function, the function has the reference and can do what it likes to it.
You also seem to misunderstand about how IIFEs hide data. You hide things inside the IIFE from things outside, not vice versa. Even then, it won't prevent you from passing a reference outside of the IIFE. Here's an example:
function changeName(animal) {
"use strict"
//myDog.name = "Rex"; // Error - myDog isn't a valid reference in this scope
//myCat.name = "Rex"; // Error - myCat isn't a valid reference in this scope either
animal.name = "Rex"; // Perfectly legal
}
(function () {
var myDog = {name: "Rover"};
var myCat = {name: "Kitty"};
console.log(myDog);
console.log(myCat);
changeName(myDog); // Even though changeName couldn't directly access myDog, if we give it a reference, it can do what it likes with it.
console.log(myDog);
})()
In this case, changeName has no access to myDog or myCat which are purely contained within the closure formed by the IIFE. However, the code that exists within that IIFE is able to pass a reference to myDog to changeName and allow it to change the name of the dog, even though changeName still couldn't access the object using the myDog variable.
This is because you are not technically redefining x, but adding properties to it.
I didn't really understood where your doubts came from so this is (to the best of my knowledge) an explanation of what your code is doing.
I'll try to translate the code to human-english.
Define the variable context in the "global scope". (It can be read from anywhere)
It cannot be redefined because its a constant.
Afterwards, define an anonymous self-invoking function (which "starts" a new "local scope" above the global scope so it has access to everything the global scope had access to)
This self invoking function grabs parameter x and adds the property y with a value of true to x and calls itself with the variable context
Read the value of context.
Please read:
JavaScript Scope
JavaScript Function Definitions (Self-Invoking Functions)

Can I access activation object of the current scope programmatically somehow?

I'm trying to some how understand what happens inside a closure and use the variables and functions created inside of it.
My limitation is that I can add as many lines of code I want to the existing closure, but cannot edit any existing ones.
Can this be done?
<script>
var scopeClone = {};
(function(scopeClone){
//Activation Object {}
scopeClone.a = "a";
var b = "b"
//Activation Object {b:"b"}
//my custom code here
//We want to copy activation object properties to scope obj
})(scope);
//At this stage, we want to get -> scopeClone.b = "b"
</script>
Not sure it can be done:
http://interglacial.com/javascript_spec/a-10.html
10.1.6 Activation Object
The activation object is purely a specification mechanism. It is impossible for an ECMAScript program to access the activation object. It can access members of the activation object, but not the activation object itself. When the call operation is applied to a Reference value whose base object is an activation object, null is used as the this value of the call.
And from here as well:
https://www.reddit.com/r/javascript/comments/2tdwcv/are_there_any_backdoor_ways_to_access_the/
Note that Activation object is an internal mechanism and is never really accessible by program code.

Is "this" necessary in javascript apart from variable definition

My question is dead simple.
I just casually discovered that once you have defined a property with this. into an object, you don't need to prepend this. anymore when you want to call them.
So this. is really meant to be used ad definition time, like var?
I found it my self shortly after, i was referencing the window object with this. since i called my object without using new, so like it was a function.
One extra question, maybe for comments. Inside the main object, if i create a new object, and use this during the object definition, this this what will be referring to?
No, unless the context of this is a global object, such as window. Take the following example:
function Foo(bar) {
this.data = bar;
console.log(this.data); // OK
console.log(data); // ReferenceError
}
In this example, you'll get a ReferenceError: data is not defined on the first console.log(data), unless, data is a global variable. To access the instance's public member, you have to use this.data.
References:
Understanding JavaScript’s this keyword
The this keyword
There are all sorts of circumstances where you MUST use this in order to reference the right data.
These two implementations do very different things:
Array.prototype.truncate(newLen) {
// sets the length property on the current Array object
this.length = newLen;
}
Array.prototype.truncate(newLen) {
// sets a global variable named length
length = newLen;
}
var arr = [1,2,3,4,5,6,7];
arr.truncate(2);
You MUST use this in order to control what happens if you want to modify the current object. Your assumption that you can leave it off and it will still modify the current object's properties is not correct. If you leave it off, you are modifying global variables, not member properties.
So this. is really meant to be used ad definition time, like var?
No, the point of this is to be the current scope of execution. You can (and will) run into weird errors if you don't use this. For example, imagine you are an object with a property val and then on the prototype of that object you have
App.obj = function(){
this.val = 'initial';
}
obj.prototype.myMethod = function(val) {
// how would you assign argument val to object val?
}
also note that your reasoning breaks down with methods.
obj.prototype.meth2 = function(){
myMethod(); // fails where this.myMethod() would work.
}
See http://jsfiddle.net/BRsqH/:
function f(){
this.public='hello!';
var hidden='TOP SECRET!';
}
var instance=new f();
alert('Public data: '+instance.public+ /* gives "hello!" */
'\nHidden data: '+instance.hidden /* gives undefined */
);
Variables created with var are hidden and cannot be viewed nor modified outside the function which created them.
But variables created with this are public, so you can access them outside the function.
I think I got it.
I defined my object as function My_Object(){...} and then called it with MyObject(). This way the My_Object was treated as a function, not an object and therefore this == window.
So in the end I was attaching properties and methods to window instead of My_Object! That's way there were available without prepending .this.
The right way to initialize My_Object as an object is to call it like this new My_Object, isn't right?

How do I reference an object method in javascript from outside the object (through event)?

I am creating a fairly complex object and want to be able to manipulate the object from the outside. I want to reference an privileged method from a click event
function myObject(){
//How do I reference this function?
this.doSomething = function (action){
var doing = action;
}
}
I understand that I could reference the method if I create the object inside a variable like:
var obj = new myObject();
obj.doSomething('hit keyboard');
But the links I am creating to trigger this event are being created by the object, but placed outside the object, so they will not know the container variable to reference it.
i.e.
Do Something
doesn't work because of course the doSomething method is part of the object, not a global function. I could rewrite the code to make it global, but would rather avoid doing that.
If this question doesn't make sense I would be happy to make it clearer. Thanks in advance.
Although it will sit in the global scope, and generally not recommended, you could do this (if you just need to get it working):
function myObject(){
//How do I reference this function?
window.doSomething = function (action){ // USE window instead of this !!
var doing = action;
}
}
By using window instead of this, it can be called in your handler.
IF the object instance is already created, then you can say:
Do Something
Otherwise,
Do Something
You need the object to be in the global scope. Try this:
window.myObject = {
doSomething: function(action) {
alert("Done!");
}
};
and then you make a click event like
Do Something
Example
To define the problem, you're in a particular object's click handler and you want to call a method on another object in your code that you can't get to directly from the object you're in. You really only have these options and you can just pick the one that seems best or seems the least objectionable:
You can make the object that you want to call a method on be in the global scope.
You can make the object that you want to call a method on be findable in the global scope (either in a parent hierarchy or with some sort of global find). It can be done this way without necessarily adding any more top level objects to the global scope.
You can set the object that you want to call a method as instance data on all objects that will have the click handler so that you can just reference the global object from the click handler object's instance data.
You can declare the click handler to have a parameter that contains your object by using function closures and avoid all global data.
The problem is that there's a disconnect between the instance of an object and the element on the page whose event should trigger the object's function. There are various ways to handle that without exposing anything globally. One way, for example, would be to tie the two via an object's property:
Give the element an ID:
<a id="myLink">Do Something</a>
Add element property to object:
function myObject(element){
this.element = element;
if (this.element) {
this.element.onclick = this.doSomething;
}
this.doSomething = function () {
// do stuffs.
}
}
Instantiate object:
var obj = new myObject(document.getElementById('myLink'));
Or simplify the object definition a bit more:
function myObject(element){
this.element = element;
if (this.element) {
this.element.onclick = function () {
// do stuffs.
}
}
}

Categories

Resources