3

To retrieve the literal object form of an instance of the global String Object in the console we simply do:

var myString = new String("Hello Stackoverflow!");
console.log(myString); 

/* console outputs: String {0: "H", 1: "e", 2: "l",..., 18: "w", 
19: "!", length: 20, [[PrimitiveValue]]: "Hello Stackoverflow!"} */

But when one creates a regular expression instance of global RegExp object and try to get the object literal form, it won't work and console will just output the regular expression pattern and flags.

var myRegexp = new RegExp("\\d+","g");
console.log(myRegexp); 

/* console outputs: /\d+/g while I would expect RegExp{..., global:true,...} 
basically the look of an object with curly braces and properties*/

How can I retrieve that regular expression object instance with all its properties and show it in the console?

KingCyrus
  • 33
  • 3

3 Answers3

2

Actually all the properties of the RexExp are not enumerable, so can't be shown in a really easy way. Moreover, overriding the toString() method of an object you can change what is going to be printed. For example:

var myRegexp = new RegExp("\\d+","g");
myRegexp.toString = function() {
  return 'I am a regex and I dont want to show my properties!';
};
console.log(myRegexp); 

Said so, I created a jsfiddle following an MDN post (the link will follow) which will print all the properties you want. I just implemented a sample in the jsfiddle and here, but you need to play a little bit with it in order to get the print as you want and with the correct properties you want

var SimplePropertyRetriever = {
    getOwnEnumerables: function(obj) {
        return this._getPropertyNames(obj, true, false, this._enumerable); 
         // Or could use for..in filtered with hasOwnProperty or just this: return Object.keys(obj);
    },
    getOwnNonenumerables: function(obj) {
        return this._getPropertyNames(obj, true, false, this._notEnumerable);
    },
    getOwnEnumerablesAndNonenumerables: function(obj) {
        return this._getPropertyNames(obj, true, false, this._enumerableAndNotEnumerable); 
        // Or just use: return Object.getOwnPropertyNames(obj);
    },
    getPrototypeEnumerables: function(obj) {
        return this._getPropertyNames(obj, false, true, this._enumerable);
    },
    getPrototypeNonenumerables: function(obj) {
        return this._getPropertyNames(obj, false, true, this._notEnumerable);
    },
    getPrototypeEnumerablesAndNonenumerables: function(obj) {
        return this._getPropertyNames(obj, false, true, this._enumerableAndNotEnumerable);
    },
    getOwnAndPrototypeEnumerables: function(obj) {
        return this._getPropertyNames(obj, true, true, this._enumerable); 
        // Or could use unfiltered for..in
    },
    getOwnAndPrototypeNonenumerables: function(obj) {
        return this._getPropertyNames(obj, true, true, this._notEnumerable);
    },
    getOwnAndPrototypeEnumerablesAndNonenumerables: function(obj) {
        return this._getPropertyNames(obj, true, true, this._enumerableAndNotEnumerable);
    },
    // Private static property checker callbacks
    _enumerable: function(obj, prop) {
        return obj.propertyIsEnumerable(prop);
    },
    _notEnumerable: function(obj, prop) {
        return !obj.propertyIsEnumerable(prop);
    },
    _enumerableAndNotEnumerable: function(obj, prop) {
        return true;
    },
    // Inspired by http://stackoverflow.com/a/8024294/271577
    _getPropertyNames: function getAllPropertyNames(obj, iterateSelfBool, iteratePrototypeBool, includePropCb) {
        var props = [];

        do {
            if (iterateSelfBool) {
                Object.getOwnPropertyNames(obj).forEach(function(prop) {
                    if (props.indexOf(prop) === -1 && includePropCb(obj, prop)) {
                        props.push(prop);
                    }
                });
            }
            if (!iteratePrototypeBool) {
                break;
            }
            iterateSelfBool = true;
        } while (obj = Object.getPrototypeOf(obj));

        return props;
    }
};
var myRegexp = new RegExp("\\d+","g");
SimplePropertyRetriever.getPrototypeNonenumerables(myRegexp).forEach(function(el) {
 console.log(el + ": " + myRegexp[el]);
});

Here the link:

https://developer.mozilla.org/it/docs/Web/JavaScript/Enumerability_and_ownership_of_properties

Here a jsfiddle:

https://jsfiddle.net/t3bp4tnq/1/

I hope this helps

quirimmo
  • 9,800
  • 3
  • 30
  • 45
  • This is really helpful thanks. I want to make sure I understand this so that we can close this topic. So (_**flags, global, etc.**_) are in fact properties of `RegExp.prototype` object and they are not existent in `myRegexp` instance. The only property existent in `myRegexp` instance seems to be `lastIndexOf` property. Now, if `global` property is defined only in the `RegExp.prototype` object where the _**value**_ of this property (specific value for this instance is `true` and we can have many instances off of global RegExp) is located? – KingCyrus May 22 '17 at 22:35
  • Ok so, let's start from the values. If you run my code snippet, you will see all the properties corresponding to your instance. Like for example: flags: g; global: true; source: \d+; If you define another regex, and call again the method I have at the end of the code, you will see all the properties associated to the new regex too. About why they don't get printed, the reason is that they are not enumerable. Following next comment, I finished the characters :D – quirimmo May 22 '17 at 22:40
  • Suppose you have a variable object like this: `var myObj = {prop1: 'test'};` If you then add a property to this object and define that not enumerable, if you try to print it it won't be displayed by default. Object.defineProperty(myObj, 'hiddenProperty', { enumerable: false, value: "my hidden property" }); Now if you `console.log(myObj);` you won't see this property. Using the methods or the function I used above, you will see also that one. Does it make sense? – quirimmo May 22 '17 at 22:42
1

console.dir prints a tree representation of the object.

console.dir(myRegexp);
alexr101
  • 588
  • 5
  • 13
  • unfortunately this method is non-standard – Ovidiu Dolha May 21 '17 at 20:08
  • Thanks for pointing that out, just to clarify, by non-standard you mean not supported in all browsers? – alexr101 May 21 '17 at 20:10
  • 2
    well it actually means it's not part of the standard specs, so even if support was implemented in most browsers it could create issues - MDN explains: `Non-standard This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.`. Of course for debugging purposes I see not harm in trying it – Ovidiu Dolha May 22 '17 at 05:47
0

Both source and global properties of myRegexp are not enumerable. You can get the values of the properties by specific reference to the properties

var myRegexp = new RegExp("\\d+","g");

var myRegexpProps = {};

var props = ["source", "flags", "global", "multiline", "sticky", "unicode"];

for (let prop of props) myRegexpProps[prop] = myRegexp[prop];

console.log(myRegexp.source, myRegexp.global, myRegexp.flags
           , myRegexp.ignoreCase, myRegexp.multiline);
           
console.log(myRegexpProps);
guest271314
  • 1
  • 15
  • 104
  • 177