Skip to main content
DBarranca
Legend
August 25, 2013
Question

How to filter Prototypes from .toSource() output?

  • August 25, 2013
  • 2 replies
  • 1682 views

Hello,

I need to write objects in a File, say that I have for instance:

var obj = {

  num: 1,

  date: new Date(),

  arr: ["a", "b"]

};

What I use to do is to stringify it first:

var strObj = obj.toSource();

$.writeln(strObj); // ({num:1, date:(new Date(1377424308540)), arr:["a", "b"]})

Which is fine.

But as soon as I add an Object prototype that I need in the script, such as:

Object.prototype.keys = function(obj) {

  var array, prop;

  array = new Array();

  for (prop in obj) {

    if (obj.hasOwnProperty(prop)) {

      array.push(prop);

    }

  }

  return array;

};

The output of the toSource() includes that keys function as well.

var strObj = obj.toSource();

$.writeln(strObj);

// ({num:1, date:(new Date(1377423260920)), arr:["a", "b"], keys:(function(obj) {   var array, prop;   array = new Array();   for (prop in obj) {  if (obj.hasOwnProperty(prop)) {    array.push(prop);  }   }   return array; })})

That's an overhead that I don't need and I'd like to get rid of. But how?

I've tried a different approach:

var Fun = function (num, date, arr) {

          this.num = num;

          this.date = date;

          this.arr = arr;

}

fun = new Fun ( 1, new Date(), ["a", "b"] );

$.writeln("fun: " + fun.toSource());

// fun: ({num:1, date:(new Date(1377424622575)), arr:["a", "b"], keys:(function(obj) {   var array, prop;   array = new Array();   for (prop in obj) {  if (obj.hasOwnProperty(prop)) {    array.push(prop);  }   }   return array; })})

but the result of the toSource() is the very same.

Any hint is appreciated!

Thanks

Davide Barranca

www.davidebarranca.com

This topic has been closed for replies.

2 replies

Kukurykus
Legend
December 30, 2017

I found a simpler way to do that you wanted including nested objects that returns correct construction of source code:

(prttps = (function() {

     Object.prototype.keys = function(v) {

          arr = []; for(i in v) {if (v.hasOwnProperty(i)) {arr.push(i)}} return arr

     }

}))()

obj = {num: 1, date: new Date(), arr: ['a', 'b'], nO: {frst: 'one', scnd: 'two'}}

for(j in obj) {

     if (!String(keys(obj)).match(RegExp('(^|,)' + j + '(,|$)'))) {

          eval('delete Object.prototype.' + j)

     }

}

(function ALRT(v) {

     function n(v){return'obj.'+(v||'')+'.toSource():'}function slc(v){return v.slice(0,-1)}

     alrt = (r = '\r\r') + r + 'AND ' + (ti = 'THIS IS ') + (on = n('nO')) + r + eval(slc(on))

     alert(ti + (o = n().replace('.', '')) + r + eval(slc(o)) + alrt); if (!v) prttps(), ALRT(1)

})()

  • You put your 'keys' prototype to instantly called function, and create your object, which may contain nested objects.
  • You use your own 'keys' prototype in "for in" loop for any existing object to solve your problem. Note that all objects (including nested ones) after creating prototype contain that prototype. So if there is 'keys' prototype in 'obj' object it will be also in 'obj.nO' object.
  • That is some wrong behaviour of Extendscript, as in Javascript those general objects doesn't exists in on-fly objects. They are only part of grandparent Object! The construction of my ALRT function was for fun. This part is not needed with its shape in your code. It has only to show that prototypes I deleted to get source code will be still present in the script environment only you call prttps function - which gathers your object prototypes - again, right after prototypes deletion to take your objects to source. So shortly saying instead of that alert you have to check source of your object and then call prttps function, that script still could use prototypes in later parts.
DBarranca
DBarrancaAuthor
Legend
August 25, 2013

This may work possibly, but just because I don't need to store functions in the object, otherwise I'd consider it a rude workaround - I haven't tested other edge cases yet:

Object.prototype.getSource = function() {

    var output = [], temp;

    for (var i in this) {

        if (this.hasOwnProperty(i)) {           

            switch (typeof this) {

                case "function" :

                    break;

                default :

                    temp = i + ":";

                    temp += this.toSource();

            }

            output.push(temp);

        }

    }

    return "{" + output.join() + "}";

}

There are slight difference but it can be refined:

getSource(): {num:(new Number(1)),date:(new Date(1377425832413)),arr:["a", "b"]}

toSource(): ({num:1, date:(new Date(1377425832413)), arr:["a", "b"]})

Davide

DBarranca
DBarrancaAuthor
Legend
August 25, 2013

Better one using recursion, that works with nested objects as well:

Object.prototype.getSource = function() {

    var output = [], temp;

    for (var i in this) {

        temp = undefined

        if (this.hasOwnProperty(i)) {    

            if (typeof this == 'object' && Object.keys(this).length > 1) {

                temp = this.getSource();

            } else temp = i + ":" + this.toSource();

        }

        if (temp) output.push(temp);

    }

    return "{" + output.join() + "}";

}

var obj = {

  num: 1,

  date: new Date(),

  arr: ["a", "b"],

  nestedObj: {

     fist: "one",

     second: "two"

  }

};

$.writeln("getSource(): " + obj.getSource())

// getSource(): {num:(new Number(1)),date:(new Date(1377428539991)),{0:(new String("a")),1:(new String("b"))},{fist:(new String("one")),second:(new String("two"))}

Slightly verbose output, though is working apparently.

Kukurykus
Legend
December 31, 2017

This is other version I satred from trying to find solution for this curious question:

(function prttps() {

     Object.prototype.tS = function() {

          for(i = 0; i < (arr = ['keys', 'tS']).length; i++) {

               eval('delete Object.prototype.' + arr)

          }

          return ttS = this.toSource(), prttps(), ttS

     }

     Object.prototype.keys = function(v) {

          arr = []; for(i in v) {

               if (v.hasOwnProperty(i)) {

                    arr.push(i)

               }

          }

          return arr

     }

})()

obj = {

     num: 1, date: new Date(), arr: ['a', 'b'],

     nO: {frst: 'one', scnd: 'two'}

}

alert(obj.tS()), /* and */ alert(obj.toSource())

alert(obj.nO.tS()), /* and */ alert(obj.nO.toSource())