⬆️ ⬇️

Javascript Property Enhancement

I bring to your attention a translation of the article " Advanced Javascript Properties " from jstips.co.



You can configure objects in javascript so that, for example, they can set the properties to be pseudo-private or readonly. This feature is available starting from ECMAScript 5.1, therefore it is supported by all browsers of the latest versions. To do this, you need to use the defineProperty method for an Object , like this:



var a = {}; Object.defineProperty(a, 'readonly', { value: 15, writable: false }); a.readonly = 20; console.log(a.readonly); // 15 


The syntax is:



 Object.defineProperty(dest, propName, options) 


Or for several properties:

')

 Object.defineProperties(dest, { propA: optionsA, propB: optionsB, //... }); 


Where options includes the following attributes:



value - if it is not getter (see below), then value is a required attribute. {a: 12} === Object.defineProperty (obj, 'a', {value: 12})

writable - sets the property to readonly. Note that if a property is nested, then it is editable.

enumerable - sets the property as hidden. This means that for ... of and stringify will not issue it in its result, although it still exists. Note. This does not mean that the property becomes private. It is still accessible from the inside, just will not be displayed.

configurable - sets the property as not changeable, for example, protected from deletion or predetermination. Again, if the property is nested, then it can be edited.



So in order to create a private persistent property, you must define it as:



 Object.defineProperty(obj, 'myPrivateProp', {value: val, enumerable: false, writable: false, configurable: false}); 


In addition to setting properties, defineProperty can define them dynamically, thanks to the second parameter, which is a string. For example, suppose I want to create properties according to some configuration:



 var obj = { getTypeFromExternal(): true // illegal in ES5.1 } Object.defineProperty(obj, getTypeFromExternal(), {value: true}); // ok // For the example sake, ES6 introduced a new syntax: var obj = { [getTypeFromExternal()]: true } 


But that's not all! Additional properties allow you to create getters and setters, like other OOP languages. However, in this case you cannot use writable, enumerable and configurable.



 function Foobar () { var _foo; // true private property Object.defineProperty(obj, 'foo', { get: function () { return _foo; } set: function (value) { _foo = value } }); } var foobar = new Foobar(); foobar.foo; // 15 foobar.foo = 20; // _foo = 20 


Except for the cases of obvious advantages of encapsulation and extended accessors, you can see that we do not “call” the getter, but get it as a property, without brackets! This is amazing! For example, let's imagine that we have an object with a bunch of nested properties:



 var obj = {a: {b: {c: [{d: 10}, {d: 20}] } } }; 


Now, instead of abc [0] .d (where one of the properties may turn out to be undefined and throw an error), we can create an alias:



 Object.defineProperty(obj, 'firstD', { get: function () { return a && ab && abc && abc[0] && abc[0].d } }) console.log(obj.firstD) // 10 


Comment



If you try to install a getter without a setter and try to set a value, you will get an error. This is especially important when using helper functions such as $ .extend or _.merge. Be careful!



Links



Source: https://habr.com/ru/post/277489/



All Articles