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.
Related
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.
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.
I've seen this syntax for creating an anonymous constructor function in JavaScript:
var Application = Application || {};
!function(window, Application) {
Application.property = {/*...*/}
Application.method = function(){/*...*/}
}(window, Application);
I want to understand what the following parts here:
What is the advantage of using first line (i.e. var o = o || {};) vs just stating var o = (function(){})();?
Why ! is used in front of function?
Why would I pass window or Application as parameters when they are global object?
Is this the most convenient way for anonymous constructor function and how is this better than:
4a)
var Application = {
property: {},
method: function(){}
}
or 4b)
var Application = (function() {
var method = function(){/*...*/}
return {method:method};
}());
The first line is to ensure that Application always exists, and is generally used in cases where it's expected that Application already should exist, and the function just augments the existing object. If it doesn't exist, this makes sure that we don't get an error for accessing properties of undefined. Your examples are only equivalent in the case where Application does not yet exist. In all other cases, your code will obliterate the existing Application, which is almost certainly not the intent.
The comment from Vatev explains what the ! does. It's another syntax for making the function in question become a self executing anonymous function. (Incidentally, it also takes the return value of the function - which is currently undefined, and flips its truthyness, so it evaluates as true. Since the result isn't stored in any variable, though, that's clearly not the purpose.)
Finally, why pass window and Application into the function and use it there? This is a safety feature, in case other code changes window or Application later on. It guarantees that within the anonymous function, window and Application are exactly what you expect it to be. In the shorthand example you gave, this may appear to not matter - after all, why protect these variables if you're using them immediately and not storing them? In many cases, you return something from this function, and then window and Application would be stored in the closure, so you'd retain the variables. It makes it safe from people who later on decide to say Application = {...}.
I don't know all of the answers but I'll try to answer what I can.
Using var Application = Application || {}; simply means that you are dealing with scope. If the "Application" variable has already be defined, it will just mean that it inherits and is now available in the current scope. If not, the "||" part (means OR) means that it will be created as an empty object. You are dealing with creating an object and then acting on it, not just having the result given back raw. That's why you shouldn't use "o = (function() {...});". "o" would then be the result of the function and not the object.
The use of "!function" causes it to be treated as an expression, but this can be tricky because you may have to think in opposites. E.g. !null means you are checking that it isn't null, not that you are checking for it to be null.
Passing in the window and Application objects deal with scoping, again. It is explicitly passing them into the function, then returning them at the end. Think of this as putting clothes in the washing machine. You put them in, stuff can happen, then you get them back out. It's a really crude idea and isn't the best example, but it's how I thought of it a while back. You put clothes in, call then rinse function, then soap function, then rinse again, then spin to drain water.
Hopefully someone else can answer that, I'm not sure what the differences are.
Since two answers so far neglected these two details: A pattern used by libraries like jQuery is using the following two parameters:
(function (window, undefined) {
window.myPlugin = ...;
})(window);
There are two things going on here:
undefined is specified as a parameter, but not passed in. This way, undefined is guaranteed to have th expected value within the inner scope. This is only necessary for older browsers which allowed overwriting undefined (though it has always been considered bad practice to do so – it's just what libraries like jQuery do to avoid other code interfering with their code).
Aliasing a global object like window within the scope allows the code to be minified more (also works for undefined). Obviously, the more references you have to the aliased object(s), the more you will save:
.
(function(w,u){w.myPlugin=...;w.somethingElse=...;if(whatever===u){return;}})(window);
compared to
(function(){window.myPlugin=...;window.somethingElse=...;if(whatever===undefined){return;}})();
You won't save much with window since typically you don't wanna clutter the global object up anyway. But aliasing undefined can save you quite some space.
Javascript copies objects by reference, rather than literally. For example:
var myObject = {};
var myCopy = myObject;
myObject.foo = "bar";
alert(myCopy.foo); //alerts "bar"
But I am really struggling to think of practical, real world reason for this other than giving developers a way to make code slightly more readable (as you can give different uses for the same object different names).
The most likely thing is I have missed the point, so can anyone tell me what that point is?
After writing:
var myObject = {};
There is an object out in memory somewhere that you can refer to by the name myObject. The following assignment:
var myCopy = myObject;
...says that myCopy now refers to that same object, wherever it may be. This is the same thing that happens when you give an argument to a function:
function somefunc(localName) {
// body
}
someFunc(myCopy);
Now there is a variable called localName that is local to someFunc that also refers to that same object out in memory.
This is the fundamental way in which we pass around references to an object, so that it can be referred to by different names, in different scopes.
We could copy the entire structure into a new location in memory. There was nothing stopping the designers from creating a language that did that. But it's less efficient -- think of deeply nested objects -- and generally not what you want to do. For example, if a function modified one property of an object, it would need to return the entire object for that change to persist outside of the function. And the caller would need to handle that return value, deciding whether the old object needs to be kept or if the newly created, slightly different copy can overwrite it.
Again, there's nothing wrong with this design direction in principle; it's just not how JavaScript was designed.
It depends; in your case it might be rather confusing since it doesn't serve a real purpose. However, for longer paths to the object it can be advantageous to store the object in a separate variable, because it requires less typing for each statement that uses the object, such as in this example:
var style = document.getElementById("foo").style;
style.color = "red";
style.font = "sans-serif";
// ...
My opinion (and it's nothing more than that) is that creating an object by reference (rather than copy) is generally more useful and what the user wants. If you pass an object as a param to a method, you're (almost always) interested in the object being worked on and altered by that method, rather than by working on a copy (and leaving the original untouched). Obviously there are circumstances where this is not true and it would be nice to have the option to choose, but I've can't recall ever finding myself wishing that I could just pass an object copy to a method, and am usually very grateful that the thing I'm working with is THE thing.
Are there any benefits to using the 'window' prefix when calling javascript variables or methods in the window object? For example, would calling 'window.alert' have an advantage over simply calling 'alert'?
I can imagine using the prefix could give a small performance boost when the call is made from inside some function/object, however I rarely see this in people's code. Henceforth this question.
This is useful when attempting to test global object values. For example, if GlobalObject is not defined then this throws an error:
if(GlobalObject) { // <- error on this line if not defined
var obj = new GlobalObject();
}
but this does not throw an error:
if(window.GlobalObject) { // Yay! No error!
var obj = new GlobalObject();
}
Similarly with:
if(globalValue == 'something') // <- error on this line if not defined
if(window.globalValue == 'something') // Hurrah!
and:
if(globalObj instanceof SomeObject) // <- error on this line if not defined
if(window.globalObj instanceof SomeObject) // Yippee! window.prop FTW!
I would not expect to see a significant performance difference, and the only other reason you might do this is to ensure that you are actually getting a value from the global scope (in case the value has been redefined in the current scope).
I doubt there is any measurable performance benefit. After all the scope chain would be scanned for the identifier window first then the window object would be scanned for the desired item. Hence more likely it would be deterimental to performance.
Using window prefix is useful if you have another variable in scope that would hide the item you may want to retrieve from the window. The question is can you always know when this might be? The answer is no. So should you always prefix with window? What would you code look like if you did that. Ugly. Hence don't do it unless you know you need to.
Retrieved from Google (http://www.techotopia.com/index.php/JavaScript_Window_Object):
The window object is the top-level object of the object hierarchy. As such, whenever an object method or property is referenced in a script without the object name and dot prefix it is assumed by JavaScript to be a member of the window object. This means, for example, that when calling the window alert() method to display an alert dialog the window. prefix is not mandatory. Therefore the following method calls achieve the same thing:
window.alert()
alert()
However, I read but have not had time to test the following from:
(http://www.javascriptref.com/reference/object.cfm?key=20)
One place you'll need to be careful, though, is in event handlers. Because event handlers are bound to the Document, a Document property with the same name as a Window property (for example, open) will mask out the Window property. For this reason, you should always use the full "window." syntax when addressing Window properties in event handlers.
As far as performance, I think AnthonyWJones has it covered.
One use of the window prefix is to explicitly make something available outside the current scope. If you were writing code in a self-invoking function to avoid polluting the global scope, but there was something within that you did want to make globally available, you might do something like the following:
(function(){
function foo(){
//not globally available
}
function bar(){
//not globally available
}
window.baz = function(){
//is globally available
foo();
bar();
};
})();
I imagine that the performance benefit here is amazingly insignificant at best, if there is one at all.
It only matters if you're using frames and doing a bunch of javascript calls across frames, and even then only specific scenarios warrant the necessity of referencing window explicitly.
When you use the prefix, you're making it explicit you're using the "global" definition of the variable, not a local one. (I'm not sure whether / how you can inject variables into a scope in JS, except the weirdness with this and inline event handlers.) YMMV, you may either prefer the clarity, or find it to be just clutter.