
Advanced objects in JavaScript - btipling
http://bjorn.tipling.com/advanced-objects-in-javascript
======
yoran
I once participated in a web security research project where we used ES6
Proxies to sandbox third-party scripts, basically controlling what DOM
operations they're allowed to do in a whitelist. This is relevant when you
include sketchy advertisement scripts or scripts you don't trust (e.g.
"trusted" scripts but delivered through an untrusted CDN). By default, no
operations were allowed and by whitelisting until there were no more errors,
we managed to effectively completely sandbox jQuery, Google Maps and Google
Analytics. None of these scripts were allowed to execute more operations than
the ones exactly required for them to function. Proxies were an elegant way to
intercept getters and setters on window, document, location, etc...

~~~
voltagex_
Are you able to link to the research? It sounds like a native-JS version of
NoScript, which is really interesting (apologies to the dead comment under me
which asked something similar)

~~~
yoran
Yep, here's the paper:
[http://www.acsac.org/2012/openconf/modules/request.php?modul...](http://www.acsac.org/2012/openconf/modules/request.php?module=oc_program&action=summary.php&id=77)

It was presented at ACSAC 2012.

------
bshimmin
Articles like this, about up-and-coming features in JavaScript, usually make
me think two things:

1) JavaScript is starting to become a "big" language, in terms of number of
keywords and syntax;

2) While many of these things that JavaScript is (finally) gaining are things
we're familiar with in other languages (and have empirically found to be
useful), they often seem somewhat more unwieldy, fiddly, and complicated in
JavaScript.

As a handwavy example, Ruby generally has most of the stuff these sorts of
articles describe, and it can be complicated at times, but usually (in my
experience) only when you're trying to do something complicated anyway; in
JavaScript, a lot of it looks quite complicated out of the box even when
you're doing something that ought to be simple.

There are many JavaScript developers out there, some with years of experience,
who are confused about, say, `var Foo = function() {}` versus `function Foo()
{}`, or the difference between `new Foo()` and `Object.create(Foo.prototype)`.
To be honest, it slightly worries me that even more complexity is being added
at this point.

~~~
btipling
JavaScript has a lot of complexity and little gotchas. I often compare the
simplicity of Go with JavaScript and wish JS were more like that, but I still
find myself enjoying JavaScript. I hope that "use strict"; evolves to further
limit the bad pit falls even experienced developers can get stuck in. Some of
the new features like isPrototypeOf can replace the old behavior, like
instanceof. I would hope that once browsers start supporting more of the new
things we all migrate to using them, if they're implemented well.

------
VeejayRampay
Good thing that this is all coming to Javascript. But I can't help but think
we're in bizarro land when the main language of the most ubiquitous medium of
the 21st century is only getting all that rather basic stuff (at least by all
the other languages' standards) in 2015 or something...

~~~
AgentME
Everything there besides Proxies and Symbols is already in common browsers,
and I can't say I'm familiar with Proxies and Symbols in other languages (not
to say some other languages necessarily don't have them, but I don't think
most users consider them basic or encounter them often).

~~~
TazeTSchnitzel
Proxies are like __get/__call in PHP, method_missing in Ruby and the similar
magic methods Python has.

Symbols are sort of JavaScript's answer to private members. Closest to __ for
members in Python.

~~~
Tloewald
I'm a bit puzzled what symbols are. If you want a unique thing that !==
anything except itself, make an empty object. It seems to me: var foo =
Symbol("foo") ought to let you dereference via bar.foo vs. bar[foo] (the
latter shouldn't even work!) or it's not what it seems it wants to be.

~~~
TazeTSchnitzel
The point of it is you can implement private properties, as I understand it:

    
    
        function MyClass() {
            var mysymbol = new Symbol("foo");
            this[mysymbol] = 3;
        }
    
        var bar = new MyClass();
        bar.foo // this won't work

~~~
Tloewald
What a convoluted mechanism! But where do you keep your reference to the
symbol to keep it private? Anywhere you keep it (e.g. in a closure somewhere)
that's private doesn't need symbols, so what problem does this solve?

And surely in your private context, bar.foo should still work.

------
jvickers
Alternatives to getType and setType functions (while still not using getters
and setters):

Have a single polymorphic function called type: type() gets the type,
type(value) sets the type.

Have .get and .set functions, called like: get('type'), set('type', value).

~~~
btipling
I like that idea, but with _Proxy_ you don't have to write the functions any
more, you could just define that one _get_ on the handler you feed into
_Proxy_ and then in your code you can access via the . notation, like:

    
    
      var obj = new Proxy(
       {foo_: "bar"}, 
       {get: function(target, name) {
         return target[name + "_"]; 
       });
      console.log(obj.foo); //logs "bar"
    

Of course maybe you'd do something a little fancier than just return the
value, like return null for property names with _ to prevent accessing private
variables. I don't know what the performance of _Proxy_ will be like, but it's
an alternative to getters and setters and lets you have a fall through for
things you haven't defined.

What I'm really excited about is reactivity on objects for setting and getting
without using functions. You could have your setter trigger events without
forcing someone to use a set function like you have in Backbone.

I think we'll see an entirely new set of model libraries because of these new
ECMAScript 5 and 6 features.

~~~
jvickers
I'm not yet excited about these getters and setters and new features in the
latest JavaScript. I've put a lot of time and effort into developing
ECMAScript (JavaScript) 3 patterns that overcome various limitations, and have
got accustomed to the idea of deploying ECMAScript 3. In terms of providing an
API, getters and setters will be very useful. It will be good to have out-of-
the-box JavaScript functionality that does not require extra code to use, like
various methods I use to overcome the ECMAScript 3 limitations.

Does anyone have an estimate for when ECMAScript 6 will be widely deployed
across browsers, almost ubiquitous? I would say now it's safe to use SVG in
many situations on the web that would not have been OK a few years ago, I'm
curious about when the tipping point will be with ECMAScript 6.

Anecdotally, recently my customers have been a lot less interested in
supporting older versions of IE, and I have used SVG in a couple of
situations, and that would not have been OK a few years back. I have not been
closely following the developments of ECMAScript 6, it has seemed like it will
be a while until it's widely deployed. The only things I have found practical
use for are typed arrays, and I have been using them in node specific code
rather than in code that I expect to run across browsers.

Though I am interested in the latest developments in JavaScript, my focus will
still be on what can be done with the JavaScript available in almost every
browser. I am also interested in making use of getters and setters in my code
but being able to compile it to ECMAScript 3, I may be able to do some
relatively simple text replacement rather than having to parse and compile an
abstract syntax tree.

~~~
cpeterso
Kangax's ES6 Compatibility Table tracks the implementation status for many
browsers, though Chrome's ES6 support is hidden behind a pref:
chrome://flags/#enable-javascript-harmony

[http://kangax.github.io/compat-table/es6](http://kangax.github.io/compat-
table/es6)

------
tomphoolery
This is pretty cool, but something about the notation confused me. Say we have
an object called "foo":

    
    
        var foo = {};
    

Is it really necessary to define properties on it with this notation?

    
    
        Object.defineProperty(foo, 'bar', { value: 'baz' });
    

Since foo itself is an Object, wouldn't it also have this method? Why can't I
define a property on foo like this?

    
    
        foo.defineProperty('bar', { value: 'baz' });

~~~
btipling
Regarding your first question, it isn't necessary to define properties with
that notation at all. You could just do:

    
    
      foo.foo = "bar";
    

But then it would be writable and configurable.

    
    
      Object.defineProperty(foo, 'bar', { value: 'baz' });
    

This foo.foo cannot be deleted. It cannot be written to. So it's a little
different. But really I was just demonstrating the use of
Object.defineProperty in a non-verbose way. You can try this out yourself, I
made a jsfiddle:
[http://jsfiddle.net/btipling/q1v3fn20/](http://jsfiddle.net/btipling/q1v3fn20/)

Regarding your second question, defineProperty is a method on Object, not
Object.prototype. "Instances" as you might call them only have direct access
to methods found on their prototype chain. You can think of
Object.defineProperty as a static method on Object if that helps. I wrote a
post about "this" which includes some information about prototypes:

[http://bjorn.tipling.com/all-this](http://bjorn.tipling.com/all-this)

You should probably first checkout the mdn documentation though:
[https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Guid...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain)

------
Excavator
Small correction: Symbol¹ is available in Firefox since back in ~June and
should arrive in Firefox Beta in ~10days.

1: [https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)

~~~
evilpie
Sadly there are still some kinks to work out so it's going to stay on Nightly
only.
[https://bugzilla.mozilla.org/show_bug.cgi?id=1041631](https://bugzilla.mozilla.org/show_bug.cgi?id=1041631)

~~~
Excavator
So earliest Release date is sometime in February then. Not that bad of a delay
at least.

Thanks for the update.

------
wging
> You can use Object.getOwnPropertyNames to get all the properties defined on
> an object. This might be a nice alternative to a for in loop.

Careful. These have different behavior for own properties which are not
enumerable. A for-in loop doesn't include them, but Object.getOwnPropertyNames
does.

~~~
TazeTSchnitzel
Right Object.keys(foo) is better.

~~~
btipling
And I also missed out on including this, thank you.

------
elwell
CoffeeScript abstracts out a lot of of awkwardness of working with JS objects.

~~~
yarrel
It does however concrete in a lot of awkwardness from working with compiling a
static language into a dynamic one then running it.

~~~
lowboy
CoffeeScript is not a static language - unless I'm misinterpreting what you
mean by "static".

And the compilation is pretty light. The syntax is different, but for the most
part the semantics are 1:1 with Javascript.

Having said that, any compile-to-language is going to introduce problems that
need to be solved. Source maps and short watch+compile times have basically
eliminated any problems for me.

