Check out a free preview of the full The Good Parts of JavaScript and the Web course

The "Meta Object API" Lesson is part of the full, The Good Parts of JavaScript and the Web course featured in this preview video. Here's what you'd learn in this lesson:

Objects have two kinds of properties: Data properties and Accessor properties. These properties are comprised of four attributes. Until ES5, these attributes were not accessible. Doug explains how the addition of the Meta Object API opens up access to property attributes.


Transcript from the "Meta Object API" Lesson

>> [MUSIC]

>> Douglas Crockford: Then we added a Meta Object API to give us more control over the attributes of the properties of objects, so we can get much finer control over what's going on. So, we now have two types of properties. We have data properties, which are the things we've always had or it's just some data that you can store in the object to retrieve and we have accessor properties.

I showed you an example earlier with the temperature object where we can have accessors and that's an, actually, have always been accessor properties in the language, but they were never exposed to you, so you couldn't make them. So there are things in the DOM like a dot innerHTML is an accessor property, that's why you can assign something to it and then something happens.

And so there was a lot of interest in allowing you to write stuff, which is as crappy as the DOM and we succeeded. So there's no limit on the crap, you can write now. So, we've got objects. Objects are composed of properties. Each property is composed of attributes.

Every property has four attributes. If you're a data property, your attributes are value, writable, enumerable and configurable. If you're an accessor property, your attributes are enumerable, configurable, get and set. So, value is the actual value of the property. Writable is a Boolean that determines if you can read it or write it, or if you can write it.

So if writeable is false, it's read only. It turns out the language has always had read only properties, but it was never exposed to you. So you couldn't create them, only the language could create them. So now, anybody can. Enumerable means it will show up in a four n loop or will show up in object.keys.

If you turn that off, it means it's not going to show up in enumerations, which means you can hide it a little bit better that it won't get dredged up all the time. Configurable means you can delete it or you can change it into an accessor property, if it was a data property.

Get is a function that will be called if you try to get the property and set is a function that will be called if you try to set the property.
>> Douglas Crockford: So having that, we've got two versions of a statement. The first statement is the way you could create an object literal in ES3 and the second one does exactly the same thing in ES5, and you might be thinking thank you very much for that.

>> Speaker 2: [LAUGH]
>> Douglas Crockford: That's huge. So the thing is we wanted to be able to add this functionality, but we were constrained that we couldn't add syntax. So we wanted to make it possible, but we couldn't make it nice. But at least possible is better than impossible, which is where we were.

So, this means that a library can now construct objects and can have control over what's going on. So, an object can designate what it wants to inherit from. It doesn't have to hear from object.prototype. It can inherit from anything or nothing. That's never been an option before, now we can do that and it can say, this property is not writeable.

It's not enumerable. It's not configurable. So, we can allow you to lock those things down. And once you set one of those things to false, it can never be turned back to true again. So that gives you some control that if you wanna lock your object down, you can now do that.

So we added a new method, Object.getProperty, which allows you to take advantage of this stuff. So, this shows an example of creating an accessory property without using new syntax. So this does something similar to what we did before, but it's only using method calls and the advantage of this form is that you can put an if around this and you won't get a syntax error if you're trying to run it on a browser that doesn't have it.

Whereas with the syntax form, you can't put an if around a syntax error. So if you try to run it on an older browser, it will simply fail
>> Douglas Crockford: So that the Meta Object API contains Object.definedProperty, which I just showed you. Object.defineProperties, which will allow you to define several of these at once and also Object.getOwnProperty descriptor, which will return an object, which describes the attributes of a property.

I should point out that this system was clearly designed by committee. You've got things like object.create and you get things like getOwnPropertyDescriptor. Committees do stuff like that. There's no consistency on how the names work. We added a couple of methods that you'll probably never get to use. GetOwnPropertyNames, getPropertyOf.

We added these for the purpose of security libraries that want to run before everything else and lockdown everything that Brendan intentionally left unlocked, so that the environment is now safe for third party code to run in your environment. And in order to get at everything that needed to be locked down, it needed special access ports drilled into the language, so he could get at this stuff.

So, what those libraries are likely to do is take these. Use them, then destroy them, so that nobody else can use them. So having all of this stuff, it becomes possible to do things that we couldn't do before. For example, this is the replace_prototype function. It makes a perfect copy of an object, except that it now inherits from a different prototype.

That's something that people have been asking for for years and there is no, until now there was no way to accomplish that. Now, there is. So the function itself is an ugly looking function, but you can wrap that in a name and now you can provide that in your library and anybody can now make an object that's got a different prototype.

>> Douglas Crockford: It used to be the case that you could add a new property to any object at any time simply by assigning to it and you can now turn that off. If you called Object.preventExtensions and pass it an object, that object will now refuse to accept new properties.

If you attempt to give it a new property, it will throw an exception instead and we can go even further than that. We can freeze the object. Freeze prevents extensions and also makes every property read-only and non-configurable, which means it is now an immutable object and that has some nice properties.

It means that future versions of the language may be able to make some interesting optimizations, because they can make assumptions that this object cannot change. That means we can be smarter in the way we generate code for that object. It also means that we can take a frozen object hand it to a third party and be confident that the third party cannot corrupt or tamper with the object and that's an extremely valuable thing, particularly as we're doing more and more complicated stuff with more parties.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now