Enumerability of properties in Javascript - javascript

How to create non-enumerable properties at construction ?
function pp_urlfield( object ) {}
pp_urlfield.prototype = Object.create( Object.prototype, {
type_internal: {
writable: true,
configurable: true,
enumerable: false,
value: ""
},
type: {
get: function() {
return this.type_internal;
},
set: function( value ) {
this.type_internal = value;
}
}
} );
If I construct this object and assign the member "type", the assignment "this.type_internal = value" creates a local and non-enumerable variable :
var a = new pp_urlfield;
a.type = 1;
//Returns ["type_internal"]
Object.keys(a);
I found a partial solution by replacing this.type_internal = value by :
Object.defineProperty(this, "type_internal", { value: value, enumerable: false });
But I think there must be a better solution.
(I don't want to use any framework, e.g. Prototype)

Related

Why I cant delete getters/setters defined in Object.defineProperties?

Somehow I can read the property of a getter, but I can't delete it.
(I can delete getters/setters defined w/o using Object.defineProperties)
var hello = {
get num() {
return 123;
}
}
delete hello.num;
// returns true
However,
var hello = {};
Object.defineProperties(hello, {
num: {
get() {
return 123;
}
}
}
delete hello.num;
// returns false
The problem is that using the .defineProperties their is a property called writable
By default, it is set to False set it to true there is also a property called configurable
set it to true as well You can see the following code example to achieve this
'use strict'
Object.defineProperty(window, 'hello',{
get: ()=>"hello to you!",
configurable: true //make this true
and for the writeable property you can set it like this:
Object.defineProperty(obj, 'key', {
enumerable: false,
configurable: True,
writable: True,
value: 'static'
});

How to retrieve corresponding object literal of a regular expression instance?

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?
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
console.dir prints a tree representation of the object.
console.dir(myRegexp);
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);

Is it possible to declare non enumerable property on javascript constructor?

I need to know if is possible to make instances of a javascript class that has non-enumerable attributes, for example
// Constructor
function MyClass(a) {
Object.defineProperty(this, '_number', {
enumerable: false
});
this.number = a; // Call setter for '_number'
}
// Getters and setters for '_number'
Object.defineProperty(MyClass.prototype, 'number', {
get: function() {
return this._number;
},
set: function(n) {
// Validate 'n' here
this._number = n;
}
});
What I wanted this code to do is to define the property _number on any instance of MyClass, making it not enumerable so that instance private variables such as _number wouldn't be listed in, suppose, a for in structure. You would use the number getter/setter to alter the private variable _number.
I have tried declaring the _number and number properties both inside the constructor and on MyClass.prototype with no success...
Any help would be appreciated!
Your approach is fine, you just need to watch out for the other attribute values which default to false:
function MyClass(a) {
Object.defineProperty(this, '_number', {
value: 0, // better than `undefined`
writable: true, // important!
enumerable: false, // could be omitted
configurable: true // nice to have
});
this.number = a; // Call setter for '_number'
}
// Getters and setters for '_number'
Object.defineProperty(MyClass.prototype, 'number', {
get: function() {
return this._number;
},
set: function(n) {
// Validate 'n' here
this._number = n;
},
enumerable: true, // to get `.number` enumerated in the loop
configurable: true // nice to have
});

TypeError: this.list.push is not a function in ecmascript 6

When calling the add function of my GroceryList class, I get an error:
TypeError: this.list.push is not a function
Why is this?
class GroceryList {
constructor() {
this.list = {
value: [],
writable: false,
enumerable: true
};
}
add(item) {
this.list.push(item);
}
getAll() {
return this.list;
}
getItemIndex(value) {
var index = this.list.length;
while(--index > -1) {
if(this.list[index] === value) {
return index;
}
}
return -1;
}
}
You are confusing
A whole object
vs
A list as an attribute of that object
The list object contains a list, but that does not mean it is a list. You should write list.value.push(x)
It seems you are trying to use a property descriptor. However, those descriptors only work with Object.defineProperty.
this.list = {
value: [],
writable: false,
enumerable: true
};
literally assigns an object with the properties value, writable and enumerable to this.list.
What you seem to want is:
Object.definProperty(this, 'list', {
value: [],
writable: false,
enumerable: true
});
Now this.list returns an array, but it's not possible to assign a new value to the property.

MDN JavaScript Inheritance Revisited - understanding the example

I was looking at the example on the MDN pages about Inheritance Revisited and thought it would be nice to have the doSomething methods actually do something. So I started out with the following code, based on the example:
function A(a) { this.varA = a };
A.prototype = { varA: null, doSomething: function() { console.log('do something with ' + this.varA) } };
function B(a, b) {
A.call(this, a);
this.varB = b;
};
B.prototype = Object.create(new A(), {
varB: { value: null, enumerable: true, configurable: true, writeable: true },
doSomething: { value: function() {
A.prototype.doSomething.apply(this, arguments);
console.log("do something with " + this.varB);
}, enumerable: true, configurable: true, writeable: true}
});
var b = new B('a', 'b');
b.doSomething();
I copy and pasted the code into the Chrome console and expected to be seeing
do something with a
do something with b
but instead I got
do something with a
do something with null
What am I overlooking here? Shouldn't the call to "new B" result in the constructor which was defined above (function B(...)) being called? And if the constructor is called, shouldn't b.varB have a value? How do I need to change the example so the output is as expected?
Accidentally you specified varB as being non-writable and hence the assignment this.varB = b failed (or was ignored).
writeable: true should be spelled writable: true (without e). By default, properties defined using the a property descriptor are non-writable.
So the whole descriptor becomes:
varB: { value: null, enumerable: true, configurable: true, writable: true }
Since you are assigning a value inside the constructor function anyway, you don't really have to use the descriptor though.
More information: MDN - Object.defineProperty.

Categories