I have a problem with dereferencing a Javascript object and setting it to NULL.
Here, I have a Folder implementation that supports recursive subdirectory removal. Please see my ments to understand my dilemma.
function Folder(name, DOM_rows) {
this.name = name;
this.files = [].concat(DOM_rows);
this.subdirs = [];
}
Folder.prototype.AddDir(name, DOM_rows) {
this.subdirs.push(new Folder(name, DOM_rows));
}
Folder.prototype.RemoveDir(folder) {
var stack = [folder];
while(stack.length > 0) {
var cur = stack.pop();
// do a post-order depth-first traversal, so dig to the deepest subdir:
if(cur.subdirs.length > 0) {
while(cur.subdirs.length > 0) { stack.push(cur.subdirs.pop()); }
} else {
// arrived at a leaf-level:
cur.files = null;
// now how do I delete cur from it's parent's subdirs array?
// the only way I know how is to keep a "cur.parentDir" reference,
// then find parent.subdirs[ index of cur ] and slice it out.
// How can I do the JS-equivalent of *cur = NULL?
}
}
}
I have a problem with dereferencing a Javascript object and setting it to NULL.
Here, I have a Folder implementation that supports recursive subdirectory removal. Please see my ments to understand my dilemma.
function Folder(name, DOM_rows) {
this.name = name;
this.files = [].concat(DOM_rows);
this.subdirs = [];
}
Folder.prototype.AddDir(name, DOM_rows) {
this.subdirs.push(new Folder(name, DOM_rows));
}
Folder.prototype.RemoveDir(folder) {
var stack = [folder];
while(stack.length > 0) {
var cur = stack.pop();
// do a post-order depth-first traversal, so dig to the deepest subdir:
if(cur.subdirs.length > 0) {
while(cur.subdirs.length > 0) { stack.push(cur.subdirs.pop()); }
} else {
// arrived at a leaf-level:
cur.files = null;
// now how do I delete cur from it's parent's subdirs array?
// the only way I know how is to keep a "cur.parentDir" reference,
// then find parent.subdirs[ index of cur ] and slice it out.
// How can I do the JS-equivalent of *cur = NULL?
}
}
}
Share
asked Nov 19, 2009 at 23:13
Jeff Meatball YangJeff Meatball Yang
39.1k27 gold badges93 silver badges125 bronze badges
2
-
Any reason you're not using recursion for
RemoveDir
? Is there any additional processing not shown in sample that needs to be performed on files or folders when they're deleted? – outis Commented Nov 20, 2009 at 0:33 - @outis: I just prefer iterative over recursive. It might be more space-effective to do it recursively in some cases, but I know that the breadth (number of subdirs at each level) will be small relative to the depth. And actually, my app isn't about folders and files, but it has the same structure. There are more properties to my "Folder" object that need to be processed and removed. – Jeff Meatball Yang Commented Nov 20, 2009 at 3:55
3 Answers
Reset to default 4Note that you don't have as big a problem as you suspect, since all subdirectories but folder
in your RemoveDir
will be deleted from their parent's subdir
by the stack.push(cur.subdirs.pop());
line
To find a subdirectory in a parent, you could make use an object-as-dictionary rather than an array for subdirs
:
function Folder(name, DOM_rows, parent) {
this.name = name;
this.parent = parent;
this.files = [].concat(DOM_rows);
this.subdirs = {};
this.subdirCount = 0;
}
Folder.prototype.AddDir = function (name, DOM_rows) {
if (this.subdirs[name]) {
return null;
}
++this.subdirCount;
return this.subdirs[name] = new Folder(name, DOM_rows, this);
}
Given a folder, you can remove the folder from the parent with:
delete folder.parent.subdirs[folder.name];
Here's a preorder version:
Folder.prototype.RemoveDir = function (folder) {
if (this.subdirs[folder.name] === folder) {
var stack = [folder];
while(stack.length > 0) {
var cur = stack.pop();
// pre-order
delete cur.files;
// if there's other processing to be done, now's the time to do it
for (subdir in cur.subdirs) {
stack.push(cur.subdirs[subdir]);
delete cur.subdirs[subdir];
}
// it's unnecessary to set subdir count, since 'cur' has been deleted
//cur.subdirCount = 0;
}
delete this.subdirs[folder.name];
--this.subdirCount;
}
}
And the recursive post-order version:
Folder.prototype.RemoveChildren = function () {
for (subdir in this.subdirs) {
this.RemoveDir(this.subdirs[subdir]);
}
}
Folder.prototype.RemoveDir = function (folder) {
if (this.subdirs[folder.name] === folder) {
folder.RemoveChildren();
folder.files = [];
delete this.subdirs[folder.name];
--this.subdirCount;
}
}
And the iterative post-order version:
Array.prototype.top = function () { return this[this.length-1]; }
Folder.prototype.RemoveDir = function (folder) {
if (this.subdirs[folder.name] === folder) {
var stack = [folder];
while(stack.length > 0) {
var cur = stack.top();
if (cur.subdirCount > 0) {
for (subdir in cur.subdirs) {
stack.push(cur.subdirs[subdir]);
delete cur.subdirs[subdir];
}
cur.subdirCount = 0;
} else {
stack.pop();
delete cur.files;
// other post-order processing
}
}
delete this.subdirs[folder.name];
}
}
Though, unless you need to take additional steps when processing deleted files & folders, a simple:
Folder.prototype.RemoveDir = function (folder) {
if (this.subdirs[folder.name] === folder) {
delete this.subdirs[folder.name];
}
}
should suffice.
Everything is javascript is passed by value, so "*cur=NULL" is not possible. You basically have the following options here
- use parentID as you suggested
- if your Folder hierarchy has a well-known root, browse from that root to find the parent object
- use something like DOM removeChild (which is called on parent), instead of removeNode (which is called on the node itself).
I was trying to do the same thing today. I've worked around it by storing the object's index as a property of the object itself.
When you add it:
myObj.ID = myArr.push(myObj);
So to remove it you
myArr[myObj.ID] = null;
I guess you solved it by now, but you could do almost the same; and it's simpler than using objects.