Overriding assignment operator in JS

var myObject = {"myKey" : "myValue"}
typeof(myObject.myKey) returns `string`

myObject.myKey = "newValue"
console.log(myObject.myKey) prints newValue

This is the expected behavior. But, similar value writes do not work for document.cookie

typeof(document.cookie) returns `string`

But performing document.cookie = "value=123", appends to document.cookie string rather than set its value to value=123

  • Setting domain-less cookies in iFrame
  • Why use encodeURIComponent() when writing json to a cookie
  • Handling User Authentication via Redux and Redux Router
  • what happens when cookies file exceeds maximum size?
  • Android webview cookie returns null
  • document.cookie is still accessible on IE11, even though cookies are disabled
  • So, how is assignment to document.cookie overridden?

  • JSON API intended for JavaScript use - handle session data server side, or in browser?
  • PHP can't remove cookie that was set by JavaScript
  • Cookie set with javascript, not recognised with PHP (same domain and path)
  • Placing a cookie with country name using geoplugin
  • Google analytics illegal cookie breaks Python backend
  • Storing Token from API w/ Express http-proxy
  • 2 Solutions collect form web for “Overriding assignment operator in JS”

    document.cookie is a little magical, but depending on your browser constraints, you an use Object.defineProperty to define properties that have different get and set behavior.

    For example:

    var obj = {};
    
    Object.defineProperty(obj, "data", {
        get: function() {return this.val; },
        set: function(val) { this.val = JSON.stringify(val); }
    });
    
    obj.data = {a:1}; // Set as an object...
    console.log(obj.data) // but retrieve as string '{"a":1}'
    

    For example, to do something similar to the cookie example, you could make a function like:

    var mixinExtender = (function mixinExtender(target) {
      var rawValue = {};
    
      Object.defineProperty(target, "data", {
        get: function() { return JSON.stringify(rawValue); },
        set: function(val) { 
          for(var key in val) {
            rawValue[key]  = val[key];
          }
        }
      });
    })
    

    This will mixin in a data property that will extend the setter value into a private object. The getter will return a serialized version of it. Then you could use it with:

    var obj = {};
    mixinExtender(obj);
    
    obj.data = {a:1};      // Add "a" key
    obj.data = {b:2};      // Add "b" key
    console.log(obj.data)  // > {"a":1,"b":2} 
    

    Browser-supplied host objects behave in ways that are not constrained by the semantics of the language. That is, document looks like a JavaScript object, but it’s not. It’s part of the runtime environment.

    The JavaScript spec is written in terms of various internal “method” descriptions. Host objects like window and document have special versions of those internal methods. Thus, the runtime follows the spec as to how the = assignment process works, but the internal method [[Put]] is simply special.