Proper subclassing of built-ins in ES5, counterproof to MDN statement - javascript

I'm writing some in-depth educational materials about the object model, constructor functions and class mechanisms in Javascript. As I was reading sources I found this statement that I took the time to understand its reasons and ultimately, I found it not to be entirely true.
The MDN article on new.target sugests using Reflect.construct in order to subclass constructor functions (of course, it also advocates for the use of class syntax in ES6 code, but my interest now is on constructor functions).
As I see it, the requirements for proper subclassing are:
the base constructor must action on the constructed object first, then the derived constructor
the constructed object's prototype must be Derived.prototype, whose prototype must be Base.prototype
the static properties should be inherited: Derived's prototype should be Base.
There is also the implicit requirement that the base constructor's prechecks for new operator usage be satisfied. This is the key difference between constructor functions pre- and post-ES6:
in ES5, this precheck consisted of a this instanceof Base check (although ECMAScript's 5.1 specification only describes the behaviours of built-ins with and without the new operator, while being ambiguous about how this check is performed).
The mdn article says:
Note: In fact, due to the lack of Reflect.construct(), it is not possible to properly subclass built-ins (like Error subclassing) when transpiling to pre-ES6 code.
and gives this example of properly subclassing Map in ES6 code:
function BetterMap(entries) {
// Call the base class constructor, but setting `new.target` to the subclass,
// so that the instance created has the correct prototype chain.
return Reflect.construct(Map, [entries], BetterMap);
}
BetterMap.prototype.upsert = function (key, actions) {
if (this.has(key)) {
this.set(key, actions.update(this.get(key)));
} else {
this.set(key, actions.insert());
}
};
Object.setPrototypeOf(BetterMap.prototype, Map.prototype);
Object.setPrototypeOf(BetterMap, Map);
const map = new BetterMap([["a", 1]]);
map.upsert("a", {
update: (value) => value + 1,
insert: () => 1,
});
console.log(map.get("a")); // 2
However, if BetterMap were defined instead as
function BetterMap(entries) {
var instance = new Map(entries);
Object.setPrototypeOf(instance, BetterMap.prototype);
return instance;
}
wouldn't we achieve the same result, both in ES5 and ES6 (after also replacing the arrow functions in the example above with function expressions)? This satisfies all the above requirements and complies with any prechecks that Map might do, as it construct the object with new.
I tested the code above with my suggested changes on Node downgraded to 5.12.0 and it worked as expected.

Wouldn't we achieve the same result, both in ES5 and ES6?
No, since Object.setPrototypeOf is not available in ES5. This was really the main limitation, you cannot subclass Array or Function in ES5 without relying on something like the non-standard (and now deprecated) .__proto__ setter. See this answer or How ECMAScript 5 still does not allow to subclass array for details.

Related

Difference between constructor function and a function that creates an object [duplicate]

Can someone clarify the difference between a constructor function and a factory function in Javascript.
When to use one instead of the other?
The basic difference is that a constructor function is used with the new keyword (which causes JavaScript to automatically create a new object, set this within the function to that object, and return the object):
var objFromConstructor = new ConstructorFunction();
A factory function is called like a "regular" function:
var objFromFactory = factoryFunction();
But for it to be considered a "factory" it would need to return a new instance of some object: you wouldn't call it a "factory" function if it just returned a boolean or something. This does not happen automatically like with new, but it does allow more flexibility for some cases.
In a really simple example the functions referenced above might look something like this:
function ConstructorFunction() {
this.someProp1 = "1";
this.someProp2 = "2";
}
ConstructorFunction.prototype.someMethod = function() { /* whatever */ };
function factoryFunction() {
var obj = {
someProp1 : "1",
someProp2 : "2",
someMethod: function() { /* whatever */ }
};
// other code to manipulate obj in some way here
return obj;
}
Of course you can make factory functions much more complicated than that simple example.
One advantage to factory functions is when the object to be returned could be of several different types depending on some parameter.
Benefits of using constructors
Most books teach you to use constructors and new
this refers to the new object
Some people like the way var myFoo = new Foo(); reads.
Drawbacks
Details of instantiation get leaked into the calling API (via the new requirement), so all callers are tightly coupled to the constructor implementation. If you ever need the additional flexibility of the factory, you'll have to refactor all callers (admittedly the exceptional case, rather than the rule).
Forgetting new is such a common bug, you should strongly consider adding a boilerplate check to ensure that the constructor is called correctly ( if (!(this instanceof Foo)) { return new Foo() } ). EDIT: Since ES6 (ES2015) you can't forget new with a class constructor, or the constructor will throw an error.
If you do the instanceof check, it leaves ambiguity as to whether or not new is required. In my opinion, it shouldn't be. You've effectively short circuited the new requirement, which means you could erase drawback #1. But then you've just got a factory function in all but name, with additional boilerplate, a capital letter, and less flexible this context.
Constructors break the Open / Closed Principle
But my main concern is that it violates the open/closed principle. You start out exporting a constructor, users start using the constructor, then down the road you realize you need the flexibility of a factory, instead (for instance, to switch the implementation to use object pools, or to instantiate across execution contexts, or to have more inheritance flexibility using prototypal OO).
You're stuck, though. You can't make the change without breaking all the code that calls your constructor with new. You can't switch to using object pools for performance gains, for instance.
Also, using constructors gives you a deceptive instanceof that doesn't work across execution contexts, and doesn't work if your constructor prototype gets swapped out. It will also fail if you start out returning this from your constructor, and then switch to exporting an arbitrary object, which you'd have to do to enable factory-like behavior in your constructor.
Benefits of using factories
Less code - no boilerplate required.
You can return any arbitrary object, and use any arbitrary prototype - giving you more flexibility to create various types of objects which implement the same API. For example, a media player that can create instances of both HTML5 and flash players, or an event library which can emit DOM events or web socket events. Factories can also instantiate objects across execution contexts, take advantage of object pools, and allow for more flexible prototypal inheritance models.
You'd never have a need to convert from a factory to a constructor, so refactoring will never be an issue.
No ambiguity about using new. Don't. (It will make this behave badly, see next point).
this behaves as it normally would - so you can use it to access the parent object (for example, inside player.create(), this refers to player, just like any other method invocation would. call and apply also reassign this, as expected. If you store prototypes on the parent object, that can be a great way to dynamically swap out functionality, and enable very flexible polymorphism for your object instantiation.
No ambiguity about whether or not to capitalize. Don't. Lint tools will complain, and then you'll be tempted to try to use new, and then you'll undo the benefit described above.
Some people like the way var myFoo = foo(); or var myFoo = foo.create(); reads.
Drawbacks
new doesn't behave as expected (see above). Solution: don't use it.
this doesn't refer to the new object (instead, if the constructor is invoked with dot notation or square bracket notation, e.g. foo.bar() - this refers to foo - just like every other JavaScript method -- see benefits).
A constructor returns an instance of the class you call it on. A factory function can return anything. You would use a factory function when you need to return arbitrary values or when a class has a large setup process.
A Constructor function example
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
new creates an object prototyped on User.prototype and calls User with the created object as its this value.
new treats an argument expression for its operand as optional:
let user = new User;
would cause new to call User with no arguments.
new returns the object it created, unless the constructor returns an object value, which is returned instead. This is an edge case which for the most part can be ignored.
Pros and Cons
Objects created by constructor functions inherit properties from the constructor's prototype property, and return true using the instanceOf operator on the constructor function.
The above behaviors can fail if you dynamically change the value of the constructor's prototype property after having already used the constructor. Doing so is rare, and it can't be changed if the constructor were created using the class keyword.
Constructor functions can be extended using the extends keyword.
Constructor functions can't return null as an error value. Since it's not an object data type, it is ignored by new.
A Factory function example
function User(name, age) {
return {
name,
age,
}
};
let user = User("Tom", 23);
Here the factory function is called without new. The function is entirely responsible for the direct or indirect use if its arguments and the type of object it returns. In this example it returns a simple [Object object] with some properties set from arguments.
Pros and Cons
Easily hides the implementation complexities of object creation from the caller. This is particularly useful for native code functions in a browser.
The factory function need not always return objects of the same type, and could even return null as an error indicator.
In simple cases, factory functions can be simple in structure and meaning.
Objects returned do not generally inherit from the factory function's prototype property, and return false from instanceOf factoryFunction.
The factory function can't be safely extended using the extends keyword because extended objects would inherit from the factory functions prototype property instead of from the prototype property of the constructor used by the factory function.
Factories are "always" better. When using object orientated languages then
decide on the contract (the methods and what they will do)
Create interfaces that expose those methods (in javascript you don't have interfaces so you need to come up with some way of checking the implementation)
Create a factory that returns an implementation of each interface required.
The implementations (the actual objects created with new) are not exposed to the factory user/consumer. This means that the factory developer can expand and create new implementations as long as he/she doesn't break the contract...and it allows for the factory consumer to just benefit from the new API without having to change their code...if they used new and a "new" implementation comes along then they have to go and change every line which uses "new" to use the "new" implementation...with the factory their code doesn't change...
Factories - better than all anything else - the spring framework is completely built around this idea.
Factories are a layer of abstraction, and like all abstractions they have a.cost in complexity. When encountering a factory based API figuring out what the factory is for a given API can be challenging for the API consumer. With constructors discoverability is trivial.
When deciding between ctors and factories you need to decide if the complexity is justified by the benefit.
Worth noting that Javascript constructors can be arbitrary factories by returning something other than this or undefined. So in js you can get the best of both worlds - discoverable API and object pooling/caching.
I think the factory function is superior to the constructor function. Using new with the constructor function, we are binding our code to one specific way of creating an object, while with a factory, we are free so we can create more different instances without binding ourselves. Let's say we have this class:
const file = new CreateFile(name)
If we want to refactor CreateFile class, creating subclasses for the file format our server supports, we can write an elegan factory function:
function CreateFile(name) {
if (name.match(/\.pdf$/)) {
return new FilePdf(name);
} else if (name.match(/\.txt$/)) {
return new FileTxt(name);
} else if (name.match(/\.md$/)) {
return new FileMd(name);
} else {
throw new Error("Not supprted file type");
}
}
with factory functions, we can implement private variables, hide the information from the users which is called encapsulation.
function createPerson(name) {
const privateInfo = {};
// we create person object
const person = {
setName(name) {
if (!name) {
throw new Error("A person must have a name");
}
privateInfo.name = name;
},
getName() {
return privateInfo.name;
},
};
person.setName(name);
return person;
}
For the differences, Eric Elliott clarified very well,
But for the second question:
When to use one instead of the other?
If you are coming from the object-oriented background, Constructor function looks more natural to you.
this way you shouldn't forget to use new keyword.

Why JavaScript objects doesn't gets copy of data and methods in ES6

One common aspect of object-oriented design (in most of the languages, especially Java) is that when we construct new object using constructor, all the methods and public/protected instance variables gets copied into the object. For example:
Car myCar = new Car('Corolla', '2015');
Now if Car class has goForward() or goBackward() methods, all of them will get copied to myCar object.
But this is not the case in JavaScript as long as I've studied. If this has been similar in JavaScript, myCarhad prototype that actually points to the Car prototype.
According to my understanding, this copying of data and methods is the ultimate requirement if we want to use class-inheritance as a design pattern. Is JavaScript really lacking this feature or just my understanding is vague? Does the new ES6 class-based structure brings this thing into picture?
Thanks for clarifying my concepts, I'm very confused over this as I've been doing things in Java in the past.
In Javascript, a constructor function contains a .prototype property that contains any methods defined for that object (either with direct assignment to the prototype in ES5 or with the class keyword in ES6).
Then, when you instantiate a new object with that constructor, the object is given a pointer to the prototype. When a method is called on that object, the Javascript interpreter will look first on the object itself for a property with that name and, if not found there, it will then go search the prototype chain.
So, the only thing that is "copied" to a newly created object in Javascript is a pointer to the prototype. And, this works identically in ES5 and ES6. The class syntax in ES6 is just new syntax for doing what we were manually doing already in ES5 (assigning methods to the prototype object).
In fact, you can even get the prototype if you want with Object.getPrototypeOf(). It's important to realize that the new object contains a pointer to the prototype object (not a copy). If subsequent changes are made to the prototype object, it is "live" and all instantiated objects before or after will see that change.
class Car {
constructor(brand, model) {
// initialize instance data
this.brand = brand;
this.model = model;
}
goForward() {
console.log("goForward");
}
goBackward() {
console.log("goBackward");
}
}
let c = new Car("Toyota", "Corolla");
console.log(Object.getPrototypeOf(c)); // shows the two methods goForward, goBackward
console.log(c.brand); // "Toyota"
Now if Car class has goForward() or goBackward() methods, all of them will get copied to myCar object.
The new object is given a pointer to the prototype. The methods are not copied individually.
According to my understanding, this copying of data and methods is the ultimate requirement if we want to use class-inheritance as a design pattern.
This is just not true. Inheritance does not require copying of all methods to the new object. There are actually many different ways to achieve proper inheritance. Javascript uses a prototype. C++ uses compile time binding. I don't know the internals of Java myself, but this post refers to a method table that each object in Java is given a pointer to.
Does the new ES6 class-based structure brings this thing into picture?
ES6 does not change how inheritance works internally in Javascript. ES6 just introduces the class syntax which is a different way of declaring an object constructor and methods, but it results in the same internal structure as the way we manually declared methods on the prototype in ES5.

Correct Javascript prototype pattern definition/example

I'm reading up on my Javascript and came across two very different Prototype pattern examples through my readings. Here is the example from Professional JavaScript for Web Developers, 3rd Edition:
Each function is created with a prototype property, which is an
object containing properties and methods that should be available to
instances of a particular reference type. This object is literally a
prototype for the object to be created once the constructor is called.
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Dev";
Person.prototype.sayName = function() {
alert(this.name);
};
var person1 = new Person();
person1.sayName(); // "Nicholas"
var person2= new Person();
person2.sayName(); // "Nicholas"
alert(person1.sayName == person2.sayName); // true
And here is the example from Learning JavaScript Design Patterns
The GoF refer to the prototype pattern as one which creates objects
based on a template of an existing object through cloning.
We can think of the prototype pattern as being based on prototypal
inheritance where we create objects which act as prototypes for other
objects. The prototype object itself is effectively used as a
blueprint for each object the constructor creates. If the prototype of
the constructor function used contains a property called name for
example (as per the code sample lower down), then each object created
by that same constructor will also have this same property.
Reviewing the definitions for this pattern in existing
(non-JavaScript) literature, we may find references to classes once
again. The reality is that prototypal inheritance avoids using classes
altogether. There isn't a "definition" object nor a core object in
theory. We're simply creating copies of existing functional objects.
One of the benefits of using the prototype pattern is that we're
working with the prototypal strengths JavaScript has to offer natively
rather than attempting to imitate features of other languages. With
other design patterns, this isn't always the case.
Not only is the pattern an easy way to implement inheritance, but it
can also come with a performance boost as well: when defining a
function in an object, they're all created by reference (so all child
objects point to the same function) instead of creating their own
individual copies.
For those interested, real prototypal inheritance, as defined in the
ECMAScript 5 standard, requires the use of Object.create (which we
previously looked at earlier in this section). To remind ourselves,
Object.create creates an object which has a specified prototype and
optionally contains specified properties as well (e.g Object.create(
prototype, optionalDescriptorObjects )).
var myCar = {
name: "Ford Escort",
drive: function () {
console.log( "Weeee. I'm driving!" );
},
panic: function () {
console.log( "Wait. How do you stop this thing?" );
}
};
// Use Object.create to instantiate a new car
var yourCar = Object.create( myCar );
// Now we can see that one is a prototype of the other
console.log( yourCar.name );
What exactly am I missing here? Is the 2nd one an updated version of the first one? Is it a different pattern entirely? Why isn't he using the .prototype in the 2nd example?
After a bunch of research it turns out that both of them are prototype patterns, even tough they look completely different and many might think that only the 1st one is right.
Yes the 2nd version is the updated one and most likely to be used.
No it's not a different pattern it's the exact prototype pattern.
The reason why it's not using .prototype is because of Object.create and how it's first argument can be an object from which it uses the prototype.
Hope this clears things up for everyone :)

practical use prototype.constructor in javascript

In Simple words why we use prototype.constructor. I am reading an article about inheritance where I saw prototype.constructor. I see no difference in result when I comment that code. So my question why and when to use it practically.
function Mammal(name){
this.name=name;
this.action= function (){
alert('0')
}
}
function Cat(name){
this.name=name;
}
Cat.prototype = new Mammal();
//Cat.prototype.constructor=Cat; // Otherwise instances of Cat would have a constructor of Mammal
Cat.prototype.action=function(){
alert('1')
}
var y= new Mammal()
var x= new Cat()
y.action()
x.action()
It's mostly convention. Although nothing in JavaScript itself uses the constructor property, sometimes people use it in their code, assuming that it will refer back to the object's constructor. It's not just convention anymore, see ¹ for details.
When you create a function:
function Cat() {
}
The function starts out with an object on its prototype property that has a property called constructor that points back to the function:
console.log(Cat.prototype.constructor === Cat); // true
This is in the specification. (It's also the only place in the specification that property is mentioned — e.g., JavaScript, itself, makes no use of this property at all. Not anymore.¹)
Consequently, instances created with that prototype (whether created via the constructor function or other ways) inherit that constructor property:
var c = new Cat();
console.log(c.constructor === Cat); // true
var c2 = Object.create(Cat.prototype);
console.log(c2.constructor === Cat); // true, even though Cat wasn't used
When you replace the prototype property on a function, as you typically do when building hierarchies:
Cat.prototype = new Mammal(); // This is an anti-pattern, btw, see below
...you end up with an object on Cat.prototype where constructor points to Mammal. Since that's not what one normally expects, it's customary to fix it:
Cat.prototype.constructor = Cat;
Although nothing in JavaScript itself uses the property (it does now¹), sometimes people use it in their code, assuming that it will refer back to the object's constructor.
Re the anti-pattern in that code: When using constructor functions to build a hierarchy, it's not best practice to actually call the "base" constructor to create the "derived" constructor's prototype. Instead, use Object.create to create the prototype:
Cat.prototype = Object.create(Mammal.prototype);
Cat.prototype.constructor = Cat;
...and then chain to Mammal in Cat:
function Cat() {
Mammal.call(this);
// ...
}
Why do it that way? Consider: What if the base requires arguments you won't get until construction-time to meaningfully initialize an instance? You can't pass it arguments until you have them. The pattern above allows you to handle that situation.
Note that Object.create was added in ES5 and so is missing from some old browsers (like IE8). The single-argument version of it can be shimmed/polyfilled trivially, though:
if (!Object.create) {
Object.create = function(proto, props) {
if (typeof props !== "undefined") {
throw new Error("The second argument of Object.create cannot be shimmed.");
}
function f() { }
f.prototype = proto;
return new f;
};
}
I'll just note that constructor functions are just one way of building object hierarchies in JavaScript. They're not the only way, because JavaScript uses prototypical inheritance. JavaScript is so powerful you can use constructor functions to get something similar to class-like inheritance, but it also lets you do more traditional prototypical-style inheritance directly.
¹ "Although nothing in JavaScript itself uses the constructor property..." That's not true anymore as of ES2015 (aka "ES6"). Now, the constructor property is used in a couple of places (such as the SpeciesConstructor and ArraySpeciesCreate abstract operations), which are used in various classes that have methods returning new instances of the class, such as Array#slice and Promise#then. It's used in those places to ensure that subclasses work correctly: E.g., if you subclass Array, and use slice on an instance of the subclass, the array returned by slice is an instance of your subclass, not a raw Array — because slice uses ArraySpeciesCreate.

What does the Reflect object do in JavaScript?

I saw a blank stub on MDN a while ago for the Reflect object in javascript but I can't for the life of me find anything on Google. Today I found this http://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect-object and it sounds similar to the Proxy object apart from the realm and loader functionality.
Basically, I don't know whether this page I found only explains how to implement Reflect or if I just can't understand its wording. Could someone please explain to me generally what the methods of Reflect do?
For instance, on the page I found says that calling Reflect.apply ( target, thisArgument, argumentsList )
will "Return the result of calling the [[Call]] internal method of target with arguments thisArgument and args." but how is that any different than just calling target.apply(thisArgument, argumentsList)?
Update:
Thanks to #Blue, I found this page on the wiki
http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect
which to the best of my knowledge says that the reflect object provides method versions of all the actions that can be trapped by proxies to make forwarding easier. But that seems a little weird to me since I don't see how it's entirely necessary. But it Seems to do a little more than that, particularly the par that says double-lifting but that points to the old proxy spec/
UPDATE 2015:
As pointed out by 7th's answer, now that ES6 (ECMAScript 2015) has been finalized, more appropriate documentation is now available:
ES6 spec, Reflection
MDN Reflect (including details and examples to all of its methods)
**Original answer (for (historic) understanding and extra examples)**:
The Reflection proposal seems to have progressed to the Draft ECMAScript 6 Specification. This document currently outlines the Reflect-object's methods and only states the following about the Reflect-object itself:
The Reflect object is a single ordinary object.
The value of the [[Prototype]] internal slot of the Reflect object is the standard built-in Object prototype object (19.1.3).
The Reflect object is not a function object. It does not have a [[Construct]] internal method; it is not possible to use the Reflect object as a constructor with the new operator. The Reflect object also does not have a [[Call]] internal method; it is not possible to invoke the Reflect object as a function.
However, there is a short explanation about it's purpose in ES Harmony:
The “#reflect” module serves multiple purposes:
Now that we have modules, a “#reflect” module is a more natural place for many of the reflection methods previously defined on Object.
For backwards-compatibility purposes, it is unlikely that the static methods on Object will disappear. However, new methods should likely be added to the “#reflect” module rather than to the Object constructor.
A natural home for proxies, avoiding the need for a global Proxy binding.
Most methods in this module map one-to-one onto Proxy traps. Proxy handlers need these methods to conveniently forward operations, as shown below.
So, the Reflect object provides a number of utility functions, many of which appear to overlap with ES5 methods defined on the global Object.
However, that doesn't really explain what existing problems this intends to solve or what functionality is added. I suspected this could be shimmed and indeed, the above harmony-spec links to a 'non-normative, approximate implementation of these methods'.
Examining that code could give (further) idea's about it's use, but thankfully there is also a wiki that outlines a number of reasons why the Reflect object is useful:
(I've copied (and formatted) the following text for future reference from that source as they are the only examples I could find. Besides that, they make sense, already have a good explanation and touch the question's apply example.)
More useful return values
Many operations in Reflect are similar to ES5 operations defined on Object, such as Reflect.getOwnPropertyDescriptor and Reflect.defineProperty. However, whereas Object.defineProperty(obj, name, desc) will either return obj when the property was successfully defined, or throw a TypeError otherwise, Reflect.defineProperty(obj, name, desc) is specced to simply return a boolean that indicates whether or not the property was successfully defined. This allows you to refactor this code:
try {
Object.defineProperty(obj, name, desc);
// property defined successfully
} catch (e) {
// possible failure (and might accidentally catch the wrong exception)
}
To this:
if (Reflect.defineProperty(obj, name, desc)) {
// success
} else {
// failure
}
Other methods that return such a boolean success status are Reflect.set (to update a property), Reflect.deleteProperty (to delete a property), Reflect.preventExtensions (to make an object non-extensible) and Reflect.setPrototypeOf (to update an object's prototype link).
First-class operations
In ES5, the way to detect whether an object obj defines or inherits a certain property name is to write (name in obj). Similarly, to delete a property, one uses delete obj[name]. While dedicated syntax is nice and short, it also means you must explicitly wrap these operations in functions when you want to pass the operation around as a first-class value.
With Reflect, these operations are readily defined as first-class functions:
Reflect.has(obj, name) is the functional equivalent of (name in obj) and Reflect.deleteProperty(obj, name) is a function that does the same as delete obj[name].
More reliable function application
In ES5, when one wants to call a function f with a variable number of arguments packed as an array args and binding the this value to obj, one can write:
f.apply(obj, args)
However, f could be an object that intentionally or unintentionally defines its own apply method. When you really want to make sure that the built-in apply function is called, one typically writes:
Function.prototype.apply.call(f, obj, args)
Not only is this verbose, it quickly becomes hard to understand. With Reflect, you can now make a reliable function call in a shorter and easier to understand way:
Reflect.apply(f, obj, args)
Variable-argument constructors
Imagine you want to call a constructor function with a variable number of arguments. In ES6, thanks to the new spread syntax, it will be possible to write code like:
var obj = new F(...args)
In ES5, this is harder to write, because one can only use F.apply or F.call to call a function with a variable number of arguments, but there is no F.construct function to new the function with a variable number of arguments. With Reflect, one can now write, in ES5:
var obj = Reflect.construct(F, args)
Default forwarding behavior for Proxy traps
When using Proxy objects to wrap existing objects, it is very common to intercept an operation, do something, and then to "do the default thing", which is typically to apply the intercepted operation to the wrapped object. For example, say I want to simply log all property accesses to an object obj:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
// now do the default thing
}
});
The Reflect and Proxy APIs were designed in tandem, such that for each Proxy trap, there exists a corresponding method on Reflect that "does the default thing". Hence, whenever you find yourself wanting to "do the default" thing inside a Proxy handler, the correct thing to do is to always call the corresponding method in the Reflect object:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
The return type of the Reflect methods is guaranteed to be compatible with the return type of the Proxy traps.
Control the this-binding of accessors
In ES5 it's fairly easy to do a generic property access or property update. For instance:
var name = ... // get property name as a string
obj[name] // generic property lookup
obj[name] = value // generic property update
The Reflect.get and Reflect.set methods allow you to do the same thing, but additionally accept as a last optional argument a receiver parameter that allows you to explicitly set the this-binding when the property that you get/set is an accessor:
var name = ... // get property name as a string
Reflect.get(obj, name, wrapper) // if obj[name] is an accessor, it gets run with `this === wrapper`
Reflect.set(obj, name, value, wrapper)
This is occasionally useful when you're wrapping obj and you want any self-sends within the accessor to get re-routed to your wrapper, e.g. if obj is defined as:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
Calling Reflect.get(obj, "foo", wrapper) will cause the this.bar() call to get rerouted to wrapper.
Avoid legacy __proto__
On some browsers, __proto__ is defined as a special property that gives access to an object's prototype. ES5 standardized a new method Object.getPrototypeOf(obj) to query the prototype. Reflect.getPrototypeOf(obj) does exactly the same, except that Reflect also defines a corresponding Reflect.setPrototypeOf(obj, newProto) to set the object's prototype. This is the new ES6-compliant way of updating an object's prototype.
Note that: setPrototypeOf also exists on Object (as correctly pointed out by Knu's comment)!
EDIT:
Side-note (addressing comments to the Q): There is a short and simple answer on 'Q: ES6 Modules vs. HTML Imports' that explains Realms and Loader objects.
Another explanation is offered by this link:
A realm object abstracts the notion of a distinct global environment,
with its own global object, copy of the standard library, and
"intrinsics" (standard objects that are not bound to global variables,
like the initial value of Object.prototype).
Extensible web: This is the dynamic equivalent of a same-origin
<iframe> without DOM.
Worth mentioning though: all this is still in draft, this is not a specification etched in stone! It's ES6, so keep browser-compatibility in mind!
Going by the draft document found on the wiki,
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
We get the line about "single ordinary object" which it clarifies in the draft. It also has the function definitions.
The wiki should be reliable since you can find a link to it from the emcascript website
http://www.ecmascript.org/dev.php
I found the first link by google though and didn't have any luck finding it by searching the wiki directly.

Categories