Search code examples
javascriptangularjsgetter-setter

Javascript doesn't throw error while trying to call get on an object


I'm trying to implement a service using AngularJS to manage cookies.

angular
    .module('myModule')
    .service('CookiesService', ['$cookies', function ($cookies) {

        var cookies = {
            cookie1: {},
            cookie2: {}
        };

        function CookiesService() {
        }

        CookiesService.prototype.update= function(name, options) {
            cookies[name] = options ? options : {};
        };


        CookiesService.prototype.isCookie = function(name) {
            if(!cookies.hasOwnProperty(name)) {
                throw 'Unknown cookie name';
            }
            return cookies.hasOwnProperty(name);
        };

        function getter(prototype, name, getter) {
            Object.defineProperty(prototype, name, {
                get:getter, 
                enumerable: true,
                configurable: true,
            });
         }

         Object.keys(cookies).forEach(function(name) {
             getter(CookiesService.prototype, name, function() {
                 try {
                      CookiesService.prototype.isCookie(name);
                      return $cookies.get(name);
                  } catch (e) {
                      throw new Error('Invalid cookie'); // never thrown!
                  }
             });

             /*Setter code*/


             return new CookiesService();
         });
     }
]);

So basically, if I want to retrieve a cookie after setting it, I would simply call CookiesServices.

Howeber, if I try to call the getter to retrieve a cookie that doesn't exist, I expect to get an error in the console. Since I have the throw, but it seems that it is not working and I am not able to debug and see whether the code gets executed at this level or not.

Example: CookiesService.cookie3 <- gives me undefined, no error thrown.

Also assuming that I do as follows:

CookiesService.prototype.isCookie = function(name) {
return cookies.hasOwnProperty(name);
};

Object.keys(cookies).forEach(function(name) {
getter(CookiesService.prototype, name, function() {
 if (!CookiesService.prototype.isCookie(name)) {
    throw new Error("blabla");
}
  return $cookies.get(name);
});

it won't throw the blabla error if I try to call CookiesService.cookie2


Solution

  • First, it might be a good idea to rename your function getter(){} to function createGetter(){}. This will make things easier to understand especially with the last param on said function also named "getter".

    Second, you stated:

    Howe[v]er, if I try to call the getter to retrieve a cookie that doesn't exist...

    This simply will never happen: Remember your foreach loop is creating getters for existing cookies (the stuff defined under var cookies). There will never be a getter defined on your service object that doesn't also have a corresponding value under cookies; thus doing something like CookiesService.cookie3 isn't calling a getter at all.

    If you think about it, how could you expect to exercise code (e.g., get: function(){...}) for a getter that's never been defined anyways?

    So calling CookiesService.cookie3 will never execute code that you setup for existing cookies and therefore will never break into your error throws.

    What you are seeing with the 'undefined' error is JS literally telling you it's not a function, it's not a getter, it's not a property... it's not anything defined on the object CookiesService.