What is the best way to delete an object in JavaScript? - javascript

In JavaScript, I have complex objects comprising functions, variables and closures.
These objects are very large, very complex and created and destroyed over and over again. I will be working on a very low-powered, very low-memory device, so it's important to me that when the objects are deleted that they are really gone.
Here's a code example:
window["obj"] = {};
obj.fun1 = function(){
console.log(1);
};
(function(){
var n = 2;
function fun(){
console.log(n);
}
obj.fun2 = fun;
})();
(function(){
var w = "Three";
function fun(){
console.log(w);
}
obj.fun3 = fun;
})();
(function(){
var w = "f.o.u.r.";
function fun(){
setInterval(function(){
console.log(w);
}, 1e3); // e.g. a timeout
}
obj.fun4 = fun;
})();
obj.fun1();
obj.fun2();
obj.fun3();
obj.fun4();
var fun2 = obj.fun2;
// window.obj = null;
// window.obj = undefined;
delete window.obj;
console.log(typeof obj); // undefined
A secondary issue is the question of "lingering references", such as the following:
fun2(); // 2
// Interval: "f.o.u.r.", "f.o.u.r.", "f.o.u.r.", "f.o.u.r." ...
Is there anything that can be done about those (except a manual clean up before deleting the object)?
A JSFiddle of the code above is here: http://jsfiddle.net/8nE2f/

You will have the best effect by doing this
window.obj = null;
delete window.obj;
Setting objects to null removes any references to it. Also remember that the delete command has no effect on regular variables, only properties.
To better ensure object destruction you may consider not using the global context at all, that is usually considered as an antipattern.

The only way to get rid of an object is for JavaScript to garbage-collect it, so making sure there really aren't any references to the object left and praying is the only way to go.
If you're repeatedly creating and destroying the same object, consider using an object pool.

Related

Is there any way to add a new parameter to a function programmatically?

Since I can determine the number of arguments a function expects to have by calling its Function.length property, is there any way for me to programmatically create the right number of parameters to insert into that function at runtime? Example:
var xyz = function(a,b) {};
var bcd = function(a,b,c,d,e,f) { }; // vararg example
var doc = document, func_length = xyz.length;
doc.xyz = (function() {
return function(a,b,c,d,e) { /* works for one but not the other */ } }).call(doc);
/* would prefer to `return function(a,b)` with only 2 parameters, if it is
used for function `xyz` (though returning 5 works fine in this case), and to
`return function(a,b,c,d,e,f)` with 6 if used for function `bcd` (which does
not work with only five params). */
// thinking about xyz.apply(null,arguments)...but which arguments..? :(
// Returning function(a,b,c,d,e) does not support functions with more than five
// parameters...which would mostly be varargs - hence my question
// I am also well aware that I can use an object or an array instead of
// using many params.
/* This is for incorporating a user-defined function for use in my code, while
* allowing for my function to do 'other stuff' afterward. (And allowing for
* varargs, of course).
* Because coding something like: doc.xyz = xyz is inflexible */
As you can see, I don't know how to do this, or if it is even possible. The search bar hasn't given me any other questions like this one, otherwise I would not have asked...
NOTE: This answer is a product of misunderstanding but
may help the future visitors of this site.
Another way:
Do you really need to add parameters? Writing the function this way would be enough:
function foo(){ //No arguments predefined
a = arguments[0] || ""; //first argument or (if not defined) empty string
b = arguments[1] || ""; //second argument etc.
c = arguments[2] || ""; //third argument etc.
alert(a+b+c);
}
foo("Hello ", "world!");
This alerts "Hello world".
The solution you want:
The simplest way:
This is what you've asked for but it's not as simple as the previous solution.
You can define a meta function with all the parameters and a handler function that changes over the time.
(function(){ //Wrapper
var foo_meta = function(a,b,c,d){ //Local meta of foo
alert(a+b+c+d); //Do the code
};
window.foo = function(a,b){ //Global foo
return foo_meta(a,b,"","");
};
window.redefine_foo = function(){ //Global foo-changer
//Rewrites foo
window.foo = function(a,b,c){
return foo_meta(a,b,c,"");
};
};
})(); //Wrapper
//Do some code
foo("a","b");
redefine_foo(); //Rewrite foo
foo("a","b","c");
//Note that foo_meta is not defined here
foo_meta == undefined; //It's safe in the wrapper :)
This will alert "ab" and then "abc". For the meaning of wrapper function, see the references.
Reference:
Arguments array: http://goo.gl/FaLM1H
Wrapping code: http://goo.gl/uQ5sd0
If you send two parameters 6 and 7 to a function doWork(a,b,c,d,e),a=7 and b=6 will be automatically set and rest of the parameters will be ignored.
Why not just pass one object into the function and use JQuery extend.
e.g.
var parm =
{ x: 1, y : 2};
f(p) {
p = $_.extend({...defaults here}, p);
...
}
This is an example for joining the arguments, regardless of the number of arguments, to show how function arguments can be turned into an array and then processed like any other array.
function foo(){ //No arguments predefined
// convert to real array
var args = Array.prototype.slice.call(arguments);
// or if Array generics are available
var args = Array.slice(arguments);
console.log(args.join(' '));
}
foo('Hello', 'world!');
foo('Hello', 'wonderful', 'world!');
Here is the fiddle
Ref: arguments MDN
Well, I think I've figured it out at last. I've realized that there may be no way to 'truly' add a parameter to a function the way that I was asking, but there is a way to emulate the same result:
var doc = document;
var xyz = function(a,b) {};
var bcd = function(a,b,c,d,e,f) {};
var obj = {};
// Now, here it is (mostly (sort of)):
obj.userFunc = function(args) {
var args_Array = [];
for (var i=0;i < arguments.length; i++ ) {
args_Array.push(arguments[i])
}
xyz.apply(null,args_Array); // or 'this'. or 'undefined'. Whatever you want.
// do other stuff
return this; // we know what to do to make 'this' scope explicit
} // end
var thisFunc = 'xyz'
doc[thisFunc] = obj.userFunc;
doc.xyz('h','i');
doc.xyz('h','i','j');
doc.xyz('h','i','j','k');
doc.xyz('h','i').xyz('j','l').xyz('j','q'); // etc.
The trick was to use the arguments object, which conveniently assimilated all the parameters into a readily available object, push each value into an array then apply the function.
In case you're wondering what the fuss was all about, I wanted to completely incorporate a user-defined function into another function, while still being able to do 'other stuff' afterward. My previous example worked to an extent, but did not have support for varargs. This does.
This approach is greatly more flexible than: doc[thisFunc] = userDefinedFunction
:) 4/26/2014

Set a global variables and use them in function (javascript)

I am new to programming and I am stuck. Here is my code:
function Subtraction() {
var a = document.getElementById('inputA').value;
var b = document.getElementById('inputB').value;
var c = (parseFloat(a) - parseFloat(b)).toFixed(5);
alert(c);
}
This works fine to me, but I have many functions that waits for onclick event to be executed. And every function have the same a and b variables. How can I get them in global scope so I don't need to wait them over and over again? I tried to put them outside of the function, but what event can trigger their declaration? There is what I tried:
var a = document.getElementById('inputA').value;
var b = document.getElementById('inputB').value;
parseFloat(a).toFixed(5);
parseFloat(b).toFixed(5);
function Subtraction() {
var c = a - b;
alert(c);
}
I see two options at least:
One is to declare them after window has loaded.
Other is to pass the elements as function parameters:
1
var a,b;
window.onload = function(){
a = document.getElementById('inputA').value;
b = document.getElementById('inputB').value;
}
2
element.onclick = function(){
var a = document.getElementById('inputA').value;
var b = document.getElementById('inputB').value;
Subtraction(a, b);
};
Btw, capital letters is used for Classes, if its a normal function better to use small "s".
You can try to declare the vars in a different javascript source file or put them in an upper block the environment of the variables holds through the entire execution from the moment you declare them so if you do this:
<script src="declare_vars.js"></script>
<script src="use_vars.js"></script>
In declare_vars.js you can try doing:
var a;
var b;
and in the other scripts use them as you want and give them the values you need, they will always be available.
The value of an input is a primitive (specifically a string) and is therefore passed by value. This means that if you do this:
var oldvalue = document.getElementById('someinput').value;
document.getElementById('someinput').value = "derp";
alert(oldvalue); // it has not changed
What you can do, if you want, is cache the result of getElementById:
var inputA = document.getElementById('inputA');
var inputB = document.getElementById('inputB');
// in your function {
var c = parseFloat(inputA.value)-parseFloat(inputB.value);
// }
This works because the result of getElementById is the input element itself. You then retrieve the desired property of this element (.value) at the specific time you need it.
That said, avoid global variables. Put variables in a scope if you want, but don't make them global.
Disclaimer: this solution makes no attempt to avoid using global variables. The usage of global variables may introduce all sorts of problems, though for an application as simple as the one described by the OP the potential pitfalls are limited.
You can add the initialization in the change event handler of each input to make sure it is always up to date:
HTML
a<input id="inputA"/>
b<input id="inputB"/>
<button id="sum">sum</button>
JAVASCRIPT
var a,b;
document.getElementById('inputA').addEventListener('change',function(evt){
a = +evt.target.value;
});
document.getElementById('inputB').addEventListener('change',function(evt){
b = +evt.target.value;
});
document.getElementById('sum').addEventListener('click', function(evt){
console.log('Sum is ' + (a+b));
});
DEMO: http://jsbin.com/EZECEraR/2/edit

Javascript: Change value of variable inside conditional inside function

I'm trying to reuse a complicated function, and it would work perfectly if I could change the value of a local variable that's inside a conditional inside that function.
To boil it down:
var func = complicated_function() {
// lots of code
if (something) {
var localvar = 35;
}
// lots of code
}
I need localvar to be some other number.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Update: The answer is yes! See my response below.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Nope.
No, but it is possible to assign it conditionally so that the function signature (basically, the required input and output) does not change. Add a parameter and have it default to its current value:
var func = complicated_function(myLocalVar) {
// lots of code
if (something) {
// if myLocalVar has not been set, use 35.
// if it has been set, use that value
var localvar = (myLocalVar === undefined)?35:myLocalVar;
}
// lots of code
}
No.
Without changing the complicated function there is no way, in javascript you can manipilate this by using call and apply. You can override functions in the complicated function or add new if this is an option (but they won't be able to access the local variable localvar).
this is more for fun my real answer is still no.
If you are feeling crazy :)
var complicatedFunction = function() {
var i = 10;
var internalStuff = function() {
console.log(i); // 10 or 12?
};
return internalStuff();
};
var complicatedFunction;
eval("complicatedFunction = " + complicatedFunction.toString().replace(/i = 10/, 'i = 12'));
complicatedFunction(); //# => 12
If the function uses this.localvar:
var func = function() {
alert(this.localvar)
if (true) {
var localvar = 35;
}
// lots of code
alert(this.localvar)
}
var obj = {localvar: 10};
func.call(obj); // alerts 10 twice
If not, then you can't change it without changing the function.
In javascript variables are "pushed" to the top of their function. Variables in javascript have function scope, not "curly brace" scope like C, C++, Java, and C#.
This is the same code with you (the developer) manually pushing it to the top:
var func = complicated_function() {
var localvar = 0;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
}
Does declaring the variable "up" one function help you out? At least the declaration is isolated.
function whatever() {
var localvar = 0;
var func = function() {
var something = true;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
};
func();
alert(localvar);
}
whatever();
Here is the jsFiddle: http://jsfiddle.net/Gjjqx/
See Crockford:
http://javascript.crockford.com/code.html
JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.
I asked this question about three weeks ago and within a half hour got five answers that all basically told me it wasn't possible.
But I'm pleased to announce that the answer is YES, it can be done!
Here's how:
var newfunc = func.toString().replace('35', '42');
eval('newfunc = ' + newfunc);
newfunc();
Of course, it uses eval, which probably means that it's evil, or at least very inadvisable, but in this particular case, it works.

How to get reference to this, when the this is override by calling the method.call(otherObject)?

var A = function(x){
var that = this;
this.a = x;
}
A.prototype = {
init: function(){
alert(this.a); // as that is not found :s
}
};
var a = new A(1);
var b = new A(2)
a.init.call(b);
// I want to alert number 1, how to do it?
I need this because I use jQuery events.
my sick solution... not so good
I got my question answered but this has some problems, I have to define a local that var and create a closure for every event... sick!
var that = this;
this.view.skinAppliedSignal.add(function(){
that.onSkinApplied();
});
// then in the onSkinApplied the this is correct. any way not so hacky to get this done?
You cannot do that, in general. The only this that exists when a function runs is the this established by the invocation.
You can "trap" things in a closure when you establish event handlers:
function something() {
$('.whatever').each(function() {
var whatever = $(this);
whatever.find('button').click(function() {
whatever.hide();
});
});
}
In that example, "whatever" is used to save the element from the "each" loop so that the event handlers hooked up to button elements can get access to it.
edit — Based on a comment and the update to the question, it's clear that perhaps what's desired is something like the ".bind()" function that's part of ES5 (and which is supplied by some libraries, like Prototype, Functional, and jQuery). By using "bind", you basically wrap any function of your choice up in another function, such that your function will always be called with this set to some specific object.
Can't be done with a prototype. You could do it this way, however:
var A = function(x){
var that = this;
this.a = x;
this.init = function(){
alert(that.a);
}
}
var a = new A(1);
var b = new A(2)
a.init.call(b);​

Add other functions later to a class without using .prototype

How do I reference to all functions added to the class, after the class has been built? (Possibly as a array) and without using prototype.
I have built a class foo(), and would like to add the functionality to add new functions
that can be used later.
var f = new foo();
then
f.addfunc('bar',function(){/*code*/});
so that f.bar(); can be used later.
Exporting (?) functions by using foo.__func_expose(funcname , function ); does not work.
(probably I am doing it the wrong way.) There seems to be a error. (see code below for detail).
The aim is to have an array containing all the functions added and the actual functions, so it can be called/replaced later.
Is it even feasible in javascript to expose new function names from within a public function?
I would like to achieve something along the line of
var MyExtendedFoo = foo();
MyExtendedFoo.__func_add("bar",(function (a, b){
alert('called : anon-func-we-named-bar'); return 2+a+b;}));
MyExtendedFoo.bar(1,3); // <---this does not work.
// It should alert a message, then return 6.
The actual code at the moment is
function foo(){
// we store reference to ourself in __self
this.__self = arguments.callee;
var self = arguments.callee;
// array that holds funcname , function
if (!self.__func_list_fname) self.__func_list_fname = [];
if (!self.__func_list_func) self.__func_list_func = [];
// allow foo.__func_expose(); register to public
self['__func_expose'] = function(){
var self = __self;
for(var i=0;i<self.__func_list_fname.length;i++){
self[''+self.__func_list_fname[i]+''] = self.__func_list_func[i];
// <---This part seems wrong. How do I do it?
};
return __self.__func_return();
};
// allow foo.__func_add( funcname , function );
self['__func_add'] = function(f,v){
var self = __self;
self.__func_list_fname.push(f);
self.__func_list_func.push(v);
// tell itself to expose the new func as well as the old ones.
return __self.__func_expose();
};
// build obj from known list and return it.
self['__func_return'] = function(){
var self = __self;
var obj = {};
obj['__func_expose'] = self['__func_expose'];
obj['__func_add'] = self['__func_add'];
obj['__func_return'] = self['__func_return'];
for(var i=0;i<self.__func_list_fname.length;i++){
obj[''+self.__func_list_fname[i]+''] = self.__func_list_func[i];
};
return obj;
};
// Return ourself so we can chain
return self.__func_return();
}
Yes. I have done my homework. I am still missing something.
http://www.crockford.com/javascript/private.html
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
http://www.stackoverflow.com/questions/55611/javascript-private-methods
#philgiese frameworks are nice, but here we want to avoid dependency, and keep it lightweight.
Besides, there's no fun to it, is there :-) Don't get me wrong, I have nothing against using prototype.
Besides the comment of #Pointy you are missing a this when you are assigning __self to var self. As I read the code __self is a variable of your foo object, so you have to reference it as this.__self when you use it.
And by the way, why aren't you using any framework for this? When I remember correctly the Prototype framework offers such functionality.
EDIT:
Just looked it up for you. This function should exactly do, what you want. AddMethods

Categories

Resources