Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

So, how is assignment to document.cookie overridden?

like image 447
zodvik Avatar asked Mar 10 '14 19:03

zodvik


People also ask

Does JS have operator overloading?

Note that you are free to overload any of the binary operators between your custom type and the JavaScript numeric types Number and BigInt . However, the only operators you are allowed to overload between your custom type and the String type are "==" and "<" .

What is assignment operator in JavaScript?

Assignment operators. An assignment operator assigns a value to its left operand based on the value of its right operand. The simple assignment operator is equal ( = ), which assigns the value of its right operand to its left operand.

Can we override equivalence comparison in JavaScript?

I'm afraid you cannot achieve such thing in Javascript. See http://www.2ality.com/2011/12/fake-operator-overloading.html for some more details.

What does {} mean in JavaScript?

So, what is the meaning of {} in JavaScript? In JavaScript, we use {} braces for creating an empty object. You can think of this as the basis for other object types. Object provides the last link in the prototype chain that can be used by all other objects, such as an Array.


2 Answers

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} 
like image 179
J. Holmes Avatar answered Oct 12 '22 01:10

J. Holmes


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.

like image 33
Pointy Avatar answered Oct 12 '22 02:10

Pointy