Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Javascript Unlocked

You're reading from   Javascript Unlocked Improve your code maintainability, performance, and security through practical expert insights and unlock the full potential of JavaScript

Arrow left icon
Product type Paperback
Published in Dec 2015
Publisher
ISBN-13 9781785881572
Length 182 pages
Edition 1st Edition
Languages
Arrow right icon
Toc

Table of Contents (10) Chapters Close

Preface 1. Diving into the JavaScript Core FREE CHAPTER 2. Modular Programming with JavaScript 3. DOM Scripting and AJAX 4. HTML5 APIs 5. Asynchronous JavaScript 6. A Large-Scale JavaScript Application Architecture 7. JavaScript Beyond the Browser 8. Debugging and Profiling Index

How to – magic methods in JavaScript

In the PHP world, there are things such as overloading methods, which are also known as magic methods (http://www.php.net/manual/en/language.oop5.overloading.php). These methods allow us to set a logic that triggers when a nonexisting property of a method is being accessed or modified. In JavaScript, we control access to properties (value members). Imagine we have a custom collection object. In order to be consistent in the API, we want to have the length property that contains the size of the collection. So we declare a getter (get length), which does the required computation whenever the property is accessed. On attempting to modify the property value, the setter will throw an exception:

"use strict";
var bar = {
 /** @type {[Number]} */
 arr: [ 1, 2 ],
 /**
  * Getter
  * @returns {Number}
  */
 get length () {
   return this.arr.length;
 },
 /**
  * Setter
  * @param {*} val
  */
 set length ( val ) {
   throw new SyntaxError( "Cannot assign to read only property 'length'" );
 }
};
console.log ( bar.length ); // 2
bar.arr.push( 3 );
console.log ( bar.length ); // 3
bar.length = 10; // SyntaxError: Cannot assign to read only property 'length'

If we want to declare getters/setters on an existing object, we can use the following:

Object.defineProperty:
"use strict";
var bar = {
 /** @type {[Number]} */
 arr: [ 1, 2 ]
};

Object.defineProperty( bar, "length", {
 /**
  * Getter
  * @returns {Number}
  */
 get: function() {
   return this.arr.length;
 },
 /**
  * Setter
  */
 set: function() {
   throw new SyntaxError( "Cannot assign to read only property 'length'" );
 }
});

console.log ( bar.length ); // 2
bar.arr.push( 3 );
console.log ( bar.length ); // 3
bar.length = 10; // SyntaxError: Cannot assign to read only property 'length'

Object.defineProperty as well as the second parameter of Object.create specifies a property configuration (whether it is enumerable, configurable, immutable, and how it can be accessed or modified). So, we can achieve a similar effect by configuring the property as read-only:

"use strict";
var bar = {};

Object.defineProperty( bar, "length", {
 /**
  * Data descriptor
  * @type {*}
  */
 value: 0,
 /**
  * Data descriptor
  * @type {Boolean}
  */
 writable: false
});

bar.length = 10; // TypeError: "length" is read-only

By the way, if you want to get rid of the property accessor in the object, you can simply remove the property:

delete bar.length;

Accessors in ES6 classes

Another way by which we can declare accessors is using the ES6 classes:

"use strict";
/** @class */
class Bar {
 /** @constructs Bar */
 constructor() {
   /** @type {[Number]} */
   this.arr = [ 1, 2 ];
 }
 /**
  * Getter
  * @returns {Number}
  */
 get length() {
   return this.arr.length;
 }
 /**
  * Setter
  * @param {Number} val
  */
 set length( val ) {
    throw new SyntaxError( "Cannot assign to read only property 'length'" );
 }
}

let bar = new Bar();
console.log ( bar.length ); // 2
bar.arr.push( 3 );
console.log ( bar.length ); // 3
bar.length = 10; // SyntaxError: Cannot assign to read only property 'length'

Besides public properties, we can control access to static ones as well:

"use strict";

class Bar {
   /**
    * @static
    * @returns {String}
    */
   static get baz() {
       return "baz";
   }
}

console.log( Bar.baz ); // baz

Controlling access to arbitrary properties

All these examples show access control to known properties. However, there might be a case when I want a custom storage with a variadic interface similar to localStorage. This must be a storage that has the getItem method to retrieve stored values and the setItem method to set them. Besides, this must work the same way as when you directly access or set a pseudo-property (val = storage.aKey and storage.aKey = "value"). These can be achieved by using the ES6 Proxy:

"use strict";
/**
* Custom storage
*/
var myStorage = {
     /** @type {Object} key-value object */
     data: {},
     /**
      * Getter
      * @param {String} key
      * @returns {*}
      */
     getItem: function( key ){
       return this.data[ key ];
     },
     /**
      * Setter
      * @param {String} key
      * @param {*} val
      */
     setItem: function( key, val ){
       this.data[ key ] = val;
     }
   },
   /**
    * Storage proxy
    * @type {Proxy}
    */
   storage = new Proxy( myStorage, {
     /**
      * Proxy getter
      * @param {myStorage} storage
      * @param {String} key
      * @returns {*}
      */
     get: function ( storage, key ) {
       return storage.getItem( key );
     },
     /**
      * Proxy setter
      * @param {myStorage} storage
      * @param {String} key
      * @param {*} val
      * @returns {void}
      */
     set: function ( storage, key, val ) {
       return storage.setItem( key, val );
   }});

storage.bar = "bar";
console.log( myStorage.getItem( "bar" ) ); // bar
myStorage.setItem( "bar", "baz" );
console.log( storage.bar ); // baz
You have been reading a chapter from
Javascript Unlocked
Published in: Dec 2015
Publisher:
ISBN-13: 9781785881572
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image