What does the Reflect object do in JavaScript? - 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.

Related

Is using `with` statement with Proxies a bad practice?

First of all, I want to clarify, I know that with is deprecated, and using it is generally a bad practice.
However, my question is about a special case: using a special Proxy object as the parameter of with.
Background
I'm working on a project, where I have to limit access of a piece of code to the global scope.
One approach might be to use a loop with eval, that creates constant variables with the value of undefined for each property of the global object, but that seems even worse than using with, and cannot limit access to variables created with let and const.
The idea
The idea is to use a Proxy as the argument of with, whose...
has trap always returns true, therefore it doesn't allow any lookups or assignments to go beyond the with statement
get trap operates normally, except that it throws ReferenceErrors when trying to access a non-existing variable (i.e. property)
set trap operates normally (or maybe contains some custom logic)
target object has no [[Prototype]] (i.e. it was created with Object.create(null))
target object has an ##unscopables property, with the value of an empty object, to allow scoping of every property
So, something like this code:
const scope = Object.create(null)
Object.assign(scope, {
undefined,
console,
String,
Number,
Boolean,
Array,
Object,
/* etc. */
[Symbol.unscopables]: Object.create(null)
})
const scopeProxy = new Proxy(scope, {
get: (obj, prop) => {
if (prop in obj)
return obj[prop]
else
throw new ReferenceError(`${prop} is not defined`)
},
set: Reflect.set,
has: () => true
})
with(scopeProxy) {
//Sandboxed code
foo = Number('42')
console.log(foo) //42
try{
console.log(scopeProxy) //Inaccessible
}catch(e){
console.error(e) //ReferenceError: scopeProxy is not defined
}
}
Avoiding contras
There are several contras listed on the MDN's page about the with statement, but this usage of it gets rid of each.
1. Performance
The problem:
Looking up identifiers that aren't a member of with statement's parameter object is less performant.
Avoidance:
No lookups can go beyond the parameter object.
2. Ambiguity
The problem:
It is hard to decide, which identifier gets looked up of those with the same name.
Avoidance:
All lookups and assignments retrieve or modify the property of the parameter object.
3. Forward compatibility
The problem:
The properties of the parameter object or its prototype might change in the future.
Avoidance:
The parameter object is initially empty and has no prototype, therefore no properties can change.
Question
The above code works perfectly, and the contras listed on MDN don't seem to apply to this case.
So, my question is:
Is it still a bad practice to use the with statement, and if so, what are the downsides of using it in this specific case?
Note: I know that this approach in itself is not secure and can be bypassed. However, this question is limited only to whether it's considered bad for some reason to use the abovementioned Proxy-with combination. In this question, I'm not concerned about security (that's a related, but different question).
Sounds like the good old lexical vs dynamic scope topic. In general lexical scope is more safe but in some situations dynamic scope makes sense, because it simplifies some solutions very much. I would say your example is one of the cases, where it may be useful.

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.

Is Object.prototype.toString a function or a property?

Before asking, I have tried to do my homework and to avoid a duplicate. Thus, I have read about 20 questions and answers (mainly on SO) which all deal with toString(). But unfortunately, none of them did answer my actual question. So here we go ...
Many examples contain code like that:
Object.prototype.toString.call(someVariable);
I just would like to know why toString can be used like a property here. I have read the reference for Object.prototype at MDN and other places. All of them list a function toString() among the members of Object.prototype, but no property toString.
Furthermore, I am using a line like that shown above at several places in my code. For testing purposes, I have added parentheses to make it "clean":
Object.prototype.toString().call(someVariable);
Obviously, that did not make it "clean", but just made it return wrong results or even made the browser stall (I am currently in the process of researching what exactly is going on).
I already have read some questions and answers regarding calling functions without parentheses. But even if I accept that the first of the code lines shown above actually calls a function (although it looks like accessing a property), that still does not explain why it goes wrong horribly when I add the parentheses as shown in the second code line. Being able to call functions without parentheses should not mean being unable to call them with parentheses, should it?
I don't think that question has an answer already (if yes, I apologize), so could anybody please give a short explanation?
Is Object.prototype.toString a function or a property?
Object.prototype.toString is a property. The value of that property is a reference to a function. Exactly like this:
var obj = {f: function() { } };
There, obj.f is a property, the value of which is a reference to a function.
The initial value of Object.prototype.toString is the intrinsic function known in the spec as %ObjProto_toString%. It can be overwritten, but doing so would like break a lot of things.
The thing to remember is that in JavaScript, functions are just objects that inherit from Function.prototype* and are callable. Just like other objects, you can keep references to them in properties and variables (you can even add properties to functions themselves), pass those references around, etc. This is in marked contrast to many languages which treat "classes" and methods and other kinds of functions as special, non-object things.
* (host-provided objects aren't required to inherit from Function.prototype, but in modern environments most do; in some obsolete browsers, some don't.)
Functions are just values. toString is a property of the Object.prototype object whose value is a function.
() is the function call operator. Object.prototype.toString doesn't call a function; it just fetches the value of the Object.prototype.toString property (which happens to be a function).
Functions are also objects, with properties of their own. That's why you can do Object.prototype.toString.call(...): This gets the Object.prototype.toString function, then fetches its call property, then calls it (which is allowed because the value of call is another function).
This works even without involving properties:
var foo = function () { return "hello"; };
var bar = foo;
console.log(bar);
console.log(bar());
The first line assigns a function value to the foo variable.
The second line assigns the same value to bar, reading from foo. Note that we're not calling the function, we're just passing it around like any other value.
The first console.log displays the function itself.
The second console.log displays the result of calling the function, because we used ().
Welcome to JavaScript. It's true that functions can be called without () in some cases (specifically, new f), but not in this case. What you see is the reference to the function being used as an object but not called (yet). That's a common thing to do, although in this case it's probably a bit more obscure than usual so I'll explain why it's done like that.
The function finally gets called when you explicitly call its call method (every function inherits that from the Function prototype), which allows you to bind this in the function body to some arbitrary object. Your first example may do the same thing as someVariable.toString(). So why use the longer form ?
Well, someVariable may not have a toString method (if it's null or undefined, because they are not objects and can't be boxed into an object), in which case using someVariable.toString would throw a TypeError. Or its prototypal toString method may have a different behaviour than the one for basic Objects. In this case, I guess that the author wanted to use an old-school trick for getting the name of an object's "species", which involves the fact that Object.prototype.toString always returns "[Object whatever]" where "whatever" will be the constructor's name or Null or Undefined.

Does New make any sense in this case?

Is there any case where a Constructor returns something on purpose and it still makes sense to new it?
var Fn = function(){
return this.fn = function(){}
}
var a = new Fn()
var b = Fn()
I can't seem to find any difference between a and b from console, but just in case I missed something, are they identical? Apart from b's side effect of adding fn as a method to window object. And if they're the same, does it mean that when a Constructor returns something, it's no longer a Constructor and shouldn't be newed?
Edit, the reason I'm asking is that I'm working with Coffee and Angular at the moment, while both seem to be pretty sensitive about return, especially with providers. Do you have any best practises regarding this?
Yes. The new invocation creates a new this context in which the function inside the constructor will be evaluated. Without it, the invocation assumes the local context and attaches your function to it. This is really important if you have multiple functions that you want to bind a unique object to.
I had the same question you did, and read the spec. I wrote about this in What the 'new' operator means to Javascript.
Arun's answer is half-right, in that it's true for the special case that you're working at the base level of the Javascript interpreter, where this === windows (or, for Node, this === global; for PLv8, this === role). Inside other objects (a really common occurrence when working with modern libraries like jQuery or Backbone!), the this operator is the local context, not the windows root.
So with the information #Elf provided, as in
When the [[Construct]] property for a Function object F is called, the following steps are taken:
Create a new native ECMAScript object.
Set the [[Class]] property of Result(1) to “Object”.
Get the value of the prototype property of the F.
If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.
Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.
If Type(Result(6)) is Object then return Result(6).
Return Result(1).
When the Constructor intentionally returns something, that something would get returned in Result(6), therefore defying the purpose of Constructors--to return Result(1) as an instance.
The only possible use of this is to take advantage of Step 6 and call the Fn with certain arguments and certain this, which, could easily be done without using Constructors and a simple call. So I guess, if Constructors return stuff, it ain't Constructor anymore.
Edit:
The interesting exception being, the object returned is Result(1) on purpose, in order to be able to take arbitrary number of arguments: Use of .apply() with 'new' operator. Is this possible?. Thanks #Elf.

Defining Functions in Object.create()

I want to create an object just using the Object.create function (without any prototype, first argument as null).
I read somewhere that properties determine the state of an object in JavaScript and JavaScript has three different kinds of properties:
named data properties
named accessor properties
internal properties
So when I define a function in an object, should I always define it as a named accessor property:
var obj = Object.create(null, {
a:{
get:function(){
alert('jQuery nyan!');
}
}
});​
Or should I just define the function as a named data property when it is neither a setter nor a getter? [e.g some jQuery functions that makes changes to the DOM obj]
var obj = Object.create(null, {
a:{
value:function(){
alert('jQuery nyan!');
}
}
});​
Which approach should I take? In terms of performance (speed) and memory management do they have differences? They both appear to work without any exception.
obj.a;
//output: 'jQuery nyan!'
To make it easier to refer to them, let's define them as follows
var objA = Object.create(null, {a: {get: function(){alert('jQuery nyan!');}}});
var objB = Object.create(null, {a: {value:function(){alert('jQuery nyan!');}}});
Now, there is almost no difference between the invocation of objA.a vs objB.a(), except the use of ().
There are some differences, however.
The main difference is that you can't pass parameters to a getter, it is invoked as-is. This means objA.a(1,2,3) will not invoke the function with arugments 1, 2, 3. It will in fact throw an error after invoking, assuming the getter does not return a Function (you're effectively trying to do undefined(1,2,3)).
A second difference requires us to remember Object.create's second parameter takes an object of descriptors, which includes the flag writable (which defaults to false). The difference here is you can not set writable:true on objA.a because "A property cannot both have accessors and be writable or have a value". This means that if you want the method of the getter changed, you must re-define the property, whereas for value you could enable the use of = to change the method associated with the property.
Additionally, with no setter objA.a = <expr> will not perform any action at all.
Normally, you'd only use getters and setters in the following instances, with value as the standard behaviour otherwise;
Lightweight calculating an output
Validating input (to protect an object)
Hiding a variable from direct access
Keeping a standard API where variable or property names may change
If you don't care about compatibility, using getter and setters could be a good approach to replace setNAME()s and getNAME()s. And there is no significant performance gain/loss comparing to function version.
Note that, cause it looks like accessing an variable, instead of calling a function, so the getter/setter function should be very light weight to meet this expectation.
And don't ever use one function for both getter and setter like jQuery does, it's simply very slow. As there is no function signature in javascript, simulate it with if/else will cause lots of performance loss.

Categories