Solid understanding to object inspections

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,787
Reaction score
939
First Language
Chinese
Primarily Uses
N/A
This post talks about more advanced concepts and techniques about inspecting objects. You're assumed to have at least:

- Some Javascript coding proficiency(Inexperienced Javascript coders having basic knowledge to the default RMMV codebase and written at least several simple but complete plugins)

- Basic knowledge to object inspections

Object Property Trees

Consider this example:

var obj_1 = { obj_prop_1: { obj_prop_1_1: {}, }, obj_prop_2: { obj_prop_2_1: [], }, obj_prop_3: [[]], obj_prop_4: [{}], obj_prop_5: [], obj_prop_6: {},};
Code:
console.log(obj_1.toSource());
Code:
({obj_prop_1:{obj_prop_1_1:{}}, obj_prop_2:{obj_prop_2_1:[]}, obj_prop_3:[[]], obj_prop_4:[{}], obj_prop_5:[], obj_prop_6:{}})
The object properties linkages can be displayed this way:

obj_1 | ----------------------------------------------------------- | | | | | | obj_prop_1 obj_prop_2 obj_prop_3 obj_prop_4 obj_prop_5 obj_prop_6 | | | |obj_prop_1_1 obj_prop_2_1 [] {}
If you know what a tree is, It's actually a tree with obj_1 as the root and all objects directly or indirectly linked to it as the leaves. The former is the parent of the latters and the latters are childrens of the former. The latters are siblings of each other and the height of that tree is 1. As it shows all object properties linked to obj_1, It's the Object Properties Tree of obj_1.

Consider another example:

var obj_1 = { obj_prop_1: { obj_prop_1_1: {}, }, obj_prop_2: { obj_prop_2_1: [], }, obj_prop_3: [[]], obj_prop_4: [{}], obj_prop_5: [], obj_prop_6: {}, obj_prop_7: obj_1,};
Code:
console.log(obj_1.toSource());
Code:
({obj_prop_1:{obj_prop_1_1:{}}, obj_prop_2:{obj_prop_2_1:[]}, obj_prop_3:[[]], obj_prop_4:[{}], obj_prop_5:[], obj_prop_6:{}, obj_prop_7:(void 0)})
The object property tree of obj_1 is this:

obj_1 | ---------------------------------------------------------------------- | | | | | | | obj_prop_1 obj_prop_2 obj_prop_3 obj_prop_4 obj_prop_5 obj_prop_6 obj_prop_7 | | | | |obj_prop_1_1 obj_prop_2_1 [] {}
Note that the obj_prop_7 part's drawn that way to indicate a cyclic linkage, meaning that what's linked to obj_prop_7 is linked by obj_1.

Also, note that

obj_prop_1 |obj_prop_1_1
Is both a subtree of the obj_1 object property tree and the object property tree of obj_prop_1.

The indirect link between obj_prop_1_1 and obj_1 are shown as the path from obj_1 to obj_prop_1_1:

obj_1 | -------------------------------- | obj_prop_1 |obj_prop_1_1
obj_prop_1_1 is a children of obj_prop_1, which is a children of obj_1, so obj_prop_1_1 is a descendant of obj_1 and obj_1 is an ancestor of obj_prop_1_1.

If the linkages of all Arrays to obj_1 are to be shown instead, the result will be this:

obj_1 | ----------------------------------- | | | | obj_prop_2 obj_prop_3 obj_prop_4 obj_prop_5 | | obj_prop_2_1 []
It combines the path from obj_1 to all Arrays, resulting in a reduced object property tree containing all Arrays.


Tree Reduction Recursions

As the root of an object's inspection tree is that object itself, the reduction always starts from the root.

In general, some specified conditions and labels will be used to determine which linked objects will remain in the reduced object property tree and mark all those picked objects respectively. That check will be used on all objects except the root in the object property tree.

When using that check on one of them, the below questions will be asked:

Q1. Does this object refer to an object that's already linked with it?

If yes, do nothing, otherwise ask Q2 and then Q3.

Q2. Does this object meet those specified conditions?

If yes, a specified label will be added to that object to notify that it'll remain in the reduced object property tree, otherwise do nothing.

Q3. Does this object contain other objects?

If yes, then Q1 will be asked on all those objects contained by that currently queried object, otherwise do nothing.

The reduction starts from asking Q3 on the root and ends with removing all objects not having that specified label and not containing any object having that specified label.

This algorithm is actually a tree recursion that uses DFS.

For example:

obj_1 | ---------------------------------------------------------------------- | | | | | | | obj_prop_1 obj_prop_2 obj_prop_3 obj_prop_4 obj_prop_5 obj_prop_6 obj_prop_7 | | | | |obj_prop_1_1 obj_prop_2_1 [] {}
The specified condition is: Is the object an Array?

The specified label is: Array

1. Ask Q3 on the root: Does obj_1 contain other objects?

- Yes(it contains obj_prop_1, obj_prop_2, obj_prop_3, obj_prop_4, obj_prop_5, obj_prop_6 and obj_prop_7), so ask Q1 on all those objects

2. Ask Q1 on obj_prop_1: Does obj_prop_1 refer to an object that's already linked with it?

- No, so ask Q2 and Q3 on obj_prop_1

3. Ask Q2 on obj_prop_1: Is obj_prop_1 an Array?

- No(it's an Object), so do nothing

4. Ask Q3 on obj_prop_1: Does obj_prop_1 contain other objects?

- Yes(it contains obj_prop_1_1), so ask Q1 on obj_prop_1_1

5. Ask Q1 on obj_prop_1_1: Does obj_prop_1_1 refer to an object that's already linked with it?

- No, so ask Q2 and Q3 on obj_prop_1_1

6. Ask Q2 on obj_prop_1_1: Is obj_prop_1_1 an Array?

- No(it's an Object), so do nothing

7. Ask Q3 on obj_prop_1_1: Does obj_prop_1 contain other objects?

- No, so do nothing

8. Ask Q1 on obj_prop_2: Does obj_prop_2 refer to an object that's already linked with it?

- No, so ask Q2 and Q3 on obj_prop_2

9. Ask Q2 on obj_prop_2: Is obj_prop_2 an Array?

- No(it's an Object), so do nothing

10. Ask Q3 on obj_prop_2: Does obj_prop_2 contain other objects?

- Yes(it contains obj_prop_2_1), so ask Q1 on obj_prop_2_1

11. Ask Q1 on obj_prop_2_1: Does obj_prop_2_1 refer to an object that's already linked with it?

- No, so ask Q2 and Q3 on obj_prop_2

12. Ask Q2 on obj_prop_2_1: Is obj_prop_2_1 an Array?

- Yes, so add the label Array to obj_prop_2_1

13. Ask Q3 on obj_prop_2_1: Does obj_prop_2_1 contain other objects?

- No, so do nothing

Similar procedures applies to the rest of the properties.
The final step is to remove all objects not having that specified label, resulting in this reduced object property tree:

obj_1 | ----------------------------------- | | | | obj_prop_2 obj_prop_3 obj_prop_4 obj_prop_5 | | obj_prop_2_1 []

Tree Reduction Plugins

While simple object property trees can be easily reduced manually, complicated ones often need custom plugins to be reduced. 1 such plugin's DoubleX RMMV Object Properties:

Plugin Calls -

//============================================================================//// ** Plugin Call Info //// A path in the object property trace will stop if it'd be cyclic ////----------------------------------------------------------------------------//// * Object manipulations //// 1. trace_obj_prop(cond, label) //// - Traces all object properties satisfying function cond linked to //// this object //// - Labels all traced object properties with function label //// - cond and label are functions written in //// Object Property Tracing Condition Function and //// Object Property Tracing Label Function respectively //// 2. _obj_prop_log[cond] //// - Returns the log of all traced object properties satisfying //// function cond linked to this object ////============================================================================//
Configurations -

//------------------------------------------------------------------------// // Object Property Tracing Condition Function // // - Setups cond used by trace_obj_prop(cond, label) // //------------------------------------------------------------------------// // cond must be a function taking the object property as the only argument // The below examples are added to help you setup your own cond functions // Checks if the currently traced object's indeed an object cond_obj: function(obj) { return typeof obj === "object"; }, // substitute cond with "cond_obj" to use this function // Checks if the currently traced object's an array cond_array: function(obj) { return Array.isArray(obj); }, // substitute cond with "cond_array" to use this function // Add your own cond functions here //------------------------------------------------------------------------// // Object Property Tracing Label Function // // - Setups label used by trace_obj_prop(cond, label) // //------------------------------------------------------------------------// // label must be a function taking the object property as the only argument // All label functions must return a string // The below examples are added to help you setup your own label functions // Always returns the entire object label_obj: function(obj) { return obj; }, // substitute label with "label_obj" to use this function // Always returns the type(including Array) of each traced object property label_array: function(obj) { if (Array.isArray(obj)) { return "array"; } return typeof obj; }, // substitute label with "label_array" to use this function // Add your own label functions here
Implementations -

// cond: The function checking whether an object property will be traced// label: The function returning the label of an traced object propertyObject.prototype.trace_obj_prop = function(cond, label) { // New if (this._obj_prop_trace === undefined) { this._obj_prop_log = {}; this._obj_prop_trace = {}; } // Stop tracing the object property if the path would be cyclic if (this._obj_prop_trace[cond] !== undefined) { return; } // this._obj_prop_log[cond] = ""; this._obj_prop_trace[cond] = {}; this.log_obj_prop(cond, label);}; // Object.prototype.trace_obj_prop// cond: The function checking whether an object property will be traced// label: The function returning the label of an traced object propertyObject.prototype.log_obj_prop = function(cond, label) { // New // Checks if the currently traced object property has object properties var has_obj_prop = false; for (prop in this) { if (this.hasOwnProperty(prop) && this.is_obj_prop(prop)) { has_obj_prop = true; break; } } // if (has_obj_prop) { this._obj_prop_log[cond] = "{"; this.traverse_obj_prop_tree(cond, label); this._obj_prop_log[cond] += "}"; }}; // Object.prototype.log_obj_prop//----------------------------------------------------------------------------//// Label and use all nonempty subtrees to form the object property tree ////----------------------------------------------------------------------------//// cond: The function checking whether an object property will be traced// label: The function returning the label of an traced object propertyObject.prototype.traverse_obj_prop_tree = function(cond, label) { // New var ot = DoubleX_RMMV.Obj_Prop; for (prop in this) { if (this.hasOwnProperty(prop) && this.is_obj_prop(prop)) { // Recursively traverse the property tree via Depth First Search var obj = this[prop]; if (ot[cond](obj)) { this._obj_prop_log[cond] += " " + prop + ": " + ot[label](obj) + " "; this._obj_prop_trace[cond][obj] = [prop]; } var temp_prop = prop; obj.trace_obj_prop(cond, label); if (Object.keys(obj._obj_prop_trace[cond]).length > 0) { if (this._obj_prop_trace[cond][obj] === undefined) { this._obj_prop_trace[cond][obj] = []; } this._obj_prop_log[cond] += " " + temp_prop + ": " + obj._obj_prop_log[cond]; this._obj_prop_trace[cond][obj].push(obj._obj_prop_trace[cond]); } // } }}; // Object.prototype.traverse_obj_prop_tree// prop: The current object property to be tracedObject.prototype.is_obj_prop = function(prop) { // New // Return false for all object properties added by this plugin if (prop === "_obj_prop_log" || prop === "_obj_prop_trace") { return false; } if (prop === "trace_obj_prop" || prop === "log_obj_prop") { return false; } return prop !== "traverse_obj_prop_tree" && prop !== "is_obj_prop"; //}; // Object.prototype.is_obj_prop
obj.trace_obj_prop(cond, label) creates the reduced object property tree of obj containing the path of all objects satisfying cond which is labeled with label and linked to obj.

Let's focus on this part:

var obj = this[prop]; if (ot[cond](obj)) { this._obj_prop_log[cond] += " " + prop + ": " + ot[label](obj) + " "; this._obj_prop_trace[cond][obj] = [prop]; } var temp_prop = prop; obj.trace_obj_prop(cond, label); if (Object.keys(obj._obj_prop_trace[cond]).length > 0) { if (this._obj_prop_trace[cond][obj] === undefined) { this._obj_prop_trace[cond][obj] = []; } this._obj_prop_log[cond] += " " + temp_prop + ": " + obj._obj_prop_log[cond]; this._obj_prop_trace[cond][obj].push(obj._obj_prop_trace[cond]); }
If an object property satisfy cond, this._obj_prop_trace[cond][obj] will store the property name to notify it satisfies cond.

It'll then create that property's own reduced object property tree and embed that tree to that of the currently queried object only if it's not empty.

If a reduced object property tree has no property storing its property name, that tree will be empty.

For the base case, it won't be empty only if the queried object satisfy cond, as the object property tree's always finite(circular references are always omitted/stopped).

So that script builds the reduced object property tree of the currently queried objects by combining those of all its nonempty subtrees(each of them is itself a reduced object property tree), meaning tree recursion's used there.

For example:

obj_1.trace_obj_prop("cond_array", "label_array")Where "cond_array" is the name of a function checking if the passed object's an Array, and "label_array" is the name of a function returning "Array".

The below shows how obj_1._obj_prop_trace["label_array"] is supposed to be built(although the plugin itself has some bugs when dealing with Arrays):

obj_1._obj_prop_trace = {};obj_1._obj_prop_trace["label_array"] = {};obj_prop_1._obj_prop_trace = {};obj_prop_1._obj_prop_trace["label_array"] = {};obj_prop_1_1._obj_prop_trace = {};obj_prop_1_1._obj_prop_trace["label_array"] = {};obj_prop_2._obj_prop_trace = {};obj_prop_2._obj_prop_trace["label_array"] = {};obj_prop_2._obj_prop_trace["label_array"][obj_prop_2_1] = ["obj_prop_2_1"];obj_prop_2_1._obj_prop_trace = {};obj_prop_2_1._obj_prop_trace["label_array"] = {};obj_prop_2._obj_prop_trace["label_array"][obj_prop_2_1] = ["obj_prop_2_1", {}];obj_1._obj_prop_trace["label_array"][obj_prop_3] = ["obj_prop_3"];obj_prop_3._obj_prop_trace = {};obj_prop_3._obj_prop_trace["label_array"] = {};obj_prop_3._obj_prop_trace["label_array"][an Array] = [an Array];obj_1._obj_prop_trace["label_array"][obj_prop_3] = ["obj_prop_3", {an Array:an Array}];obj_1._obj_prop_trace["label_array"][obj_prop_4] = ["obj_prop_4"];obj_prop_4._obj_prop_trace = {};obj_prop_4._obj_prop_trace["label_array"] = {};obj_1._obj_prop_trace["label_array"][obj_prop_5] = ["obj_prop_5"];obj_prop_5._obj_prop_trace = {};obj_prop_5._obj_prop_trace["label_array"] = {};obj_prop_6._obj_prop_trace = {};obj_prop_6._obj_prop_trace["label_array"] = {};obj_prop_7._obj_prop_trace = {};
This should show that that script uses depth first search to run the recursion.

The result's supposed to be something like this:

console.log(obj_1._obj_prop_trace["label_array"].toSource());
Code:
({obj_prop_2_1:["obj_prop_2_1", {}], obj_prop_3:["obj_prop_3", {an Array:an Array}], obj_prop_4:["obj_prop_4"], obj_prop_5:["obj_prop_5"]})
Once you understand how obj_1._obj_prop_trace["label_array"] is built, you should understand how obj_1._obj_prop_cond["label_array"] is built too.


That's all for now. I hope this can help you grasp these more advanced stuffs. For those comprehending object inspections, feel free to correct me if there's anything wrong :D
 
Last edited by a moderator:

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

How many parameters is 'too many'??
Yay, now back in action Happy Christmas time, coming back!






Back in action to develop the indie game that has been long overdue... Final Fallacy. A game that keeps on giving! The development never ends as the developer thinks to be the smart cookie by coming back and beginning by saying... "Oh bother, this indie game has been long overdue..." How could one resist such? No-one c
So I was playing with filters and this looked interesting...

Versus the normal look...

Kind of gives a very different feel. :LZSexcite:
To whom ever person or persons who re-did the DS/DS+ asset packs for MV (as in, they are all 48x48, and not just x2 the pixel scale) .... THANK-YOU!!!!!!!!! XwwwwX

Forum statistics

Threads
105,849
Messages
1,016,981
Members
137,563
Latest member
cexojow
Top