So I was coding today and I found odd that
arguments.concat(someNumber);
gave me an error for undefined function. At first I thought that arguments might be some kind of native object for performance reasons, but in the end I found out it is in fact a plain javascript object and not an array or internal native object. I was left wondering if there is any special reason for that.
The arguments object is special ("exotic" in Harmony parlance) because it maintains the live connection between its own numeric properties and scope variables:
function x(a) {
arguments[0] = 42;
document.write(a);
}
x(10)
To support this functionality, arguments needs to override a lot of stuff from the default object. That's why it's a separate type.
Related
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.
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.
In JavaScript, objects have properties and values:
var o = {
prop1: "value",
prop2: 3
}
My understanding is all JavaScript objects must look like this (i.e. have properties and values only). But, functions (I'm not talking about methods) are objects too:
function f() {
console.log("Hello");
}
Why is it possible for my function object to differ from the {property:value} style of object that is o?
Update: To try to explain my question further:
Objects are described in almost every book I've ever read as string to value maps. For example, they map a property name to a property value:
{
property1: value,
property2: value
}
Functions are objects, however they do not look at all like string to value maps:
function my_f() {
// code here.
}
Why are function objects allowed to differ from the string to value map format?
Well, In javascript, functions can be treated as Classes in other Object Oriented Languages.
This means that you can instantiate a new object from the function using the new keyword
Example:
function myFunc(){
//Some code goes here
}
var myObj = new myFunc();
You can attach properties to this Class using this keyword
Example:
function myFunc(){
//this is a public property for any myFunc object
this.name="My_Name";
//this is a private property
var age = 22;
}
var myObj = new myFunc();
console.log(myObj.name); //Will output "My_Name"
console.log(myObj.age); //undefined
Everything is object in JS.
var o = {
prop1: "value",
prop2: 3
}
is just a shortcut for object creation instead of using the Object constructor(and is fast too). Same goes with functions.
Consider
var adder = new Function('a', 'b', 'return a + b'); console.log(adder.prototype)
Its an object with the constructor and other properties with corresponding values.
I think what you're asking about is, at its heart, the difference between a function declaration and a function expression. These are just different ways that Javascript allows variables/properties of type Function to be created.
You can, of course, define a function as the inline value for a property, as you would any object literal:
var Foo = {
bar: function(){
console.log("bar");
}
};
You can also define as a property this way:
var Foo = {};
Foo.bar = function(){
console.log("bar");
};
Or you can assign the result of the function expression directly to a variable:
var bar = function(){
console.log("bar");
};
These examples should demonstrate that functions are like any other variable/property in Javascript. They have a type, just like a String or a Number. A string is also an object, but you don't need curly braces to create a string:
var foo = "foo";
A function declaration, as you're describing in your question is a slightly different way of defining a function:
function bar(){
console.log("bar");
}
I believe that they included this additional function syntax in the language for one main reason: hoisting.
Including this alternate syntax that hoists function declarations "up above" other expressions allows coders to be a little bit more loose with the order in which they define their variables and functions.
There are arguments to be made both in favor of function declarations and function expressions, but I tend to use the function expression syntax, as I like that it is more consistent and less surprising for new team members.
UPDATE:
Perhaps you are overthinking this idea that "Objects are described in almost every book I've ever read as string to value maps. For example, they map a property name to a property value:"
A string is an Object, a function is also still an Object. Try this:
var foo = "foo";
foo.bar = "bar";
console.log(foo, foo.bar);
Or this:
var foo = function(){
console.log("foo");
};
foo.bar = function(){
console.log("bar");
};
console.log(foo(), foo.bar());
The syntax for creating object literals in Javascript can involve defining the key/value pairs, yes. But there are lots of ways to create variables and properties of various types, many of which ultimately inherit from the Object prototype, including the Function type.
The different syntaxes all result in the same types of Objects being created. The only thing that matters is the order of declaration/execution, as defined by the hoisting rules.
After 5 minutes of looking into your question with a wierd look i think i finally understood what you want to know.
You, in-fact, ask why is the consistency of the Object in javascript is different when using function or key:value kind of option.
Well, javascript is a
dynamic, weakly typed, prototype-based language with first-class functions
If I can quote wikipedia here.
This means that everything in this so-called language is Object base, if you know c# from example, its like everything is object type and there aren't any other primitive-type objects.
With that being said, object is mostly like a memory entry and not a real value of things, unlike int, string, char etc.
Therefore, functions are actually stored in memory as same as objects do.
if you look on other elite-type languages you can see that object there can store perhaps everything, even an entire solution, it doesn't have any bounds.
In unrelated matter, I would like to recommend you to read about "boxing" and "unboxing" of elements to understand the idea behind objectifying stuff.
Why are function objects allowed to differ from the string to value map format?
Exactly because its just a memory reference and the "syntax" isn't really important, if you try to execute some operation that belongs to a method and not for a normal type object like {key: "value"} the execute will first approach the object in the memory and try to operate () on it, it will throw an error unless the () operation is defined for this object.
hope I made myself clear enough
EDIT
ok, ill explain more, as you wish.
basically there are 2 ways in which data storing is occurring.
Heap memory (not the data structure), if to quote Wikipedia again is
very simple explanation is that the heap is the portion of memory where dynamically allocated memory resides
In easy words, it means you save something by its value and you use it in different ways as value.
so you ask yourself, what does it mean "not by value"
Memory reference (stack), that means that every non-primitive object you create is assigned with its own memory address, in fact every time you create an object you're allocating space in your memory, just to be clear, all javascript's data storing is done by this way, unlike any elite-type language such as java,c,c++,c# and so on..
now, why am i saying this?
because when i create an object, a reference, i can create a reference to whatever i want to, it can be an object that describes Human, function, document or even a file. I will be very careful with what im about to say, javascript doesnt let you distinct between objects, an object is an object, of course each has its own properties, but that is only important when you try to execute things with that object.
if you are familiar with c# (always bringing this up because its commonly wide-spread language) you'll notice that you have both objects that you create, methods, threads,task,solutions and possibly every type of data, and they are all objects before they are themselves.
as to conclude:
object in javascript is a matter of principle and not data type.
encourage you strongly to read an article, heap vs stack
After doing a little more research of my own, I found out function objects are a special type of object. Aside from being a regular object which has any number of properties and values, function objects are also callable blocks of code. This extra "capability" (I couldn't think of a better term) is something that is added by JavaScript itself.
What do you call an object with a function in it. I'm documenting some functions that return this with jsdoc and I'm having trouble sticking with one way of conveying this.
This is what I'm returning
{fnName: [function]}
or
{fnNameA: [function], fnNameB: [function]}
My problem documenting the return value this way is conveying not to expect property as literal object.fnName and as a variable function name.
How do I represent this in jsdocs? Is the above the standard?
What do we as programmers call this kind of variable?
Object where values are functions
Object with functions
Object with function properties
Object with methods
Object with named function properties
Is there one word that conveys this?
The proper programming answer is Object with methods. This is because the property's value is a function, whether named or not. But it should be understood that a method is simply a property that is a function. The reason we distinguish them is that interacting with them properly requires a slightly different signature, resulting in an invocation. However, it should be noted that other terms might apply depending upon usage and accessibility. For instance, if the object is to be used by a code consumer, API might also apply.
An important clarification:
They are only named functions if the function has a name (a property name is not a function name). For example, the below would be a named function:
{
prop1: function myFn() {
}
}
I never seen special distinction for "object that only have properties with functions as values".
I'd use: "Object with properties" or maybe "object with methods" (as I'm from more strongly typed world).
If result normally used as argument of another function - "options object" (as in options JavaScript pattern ).
Question
Is there a performance advantage in using an object literal over a self instantiated constructor?
Examples
Object literal:
var foo = {
//...
};
Self instantiated constructor:
var foo = new function () {
//...
};
Yes (the object literal will be faster), but they are subtly different in implementation1 and represent different goals. The constructor form "has to do a bunch more stuff" while the literal form can also be more highly optimized - it is a definition (of an as-of-yet-fixed set of properties), and not a sequence of statements.
Even though a micro-benchmark (which is interesting, thanks Arun!) might show one being "much slower", it Just Doesn't Matter in a real program2 as the amount of relative time spent in either construct approaches nothing.
1 When a constructor is used a prototype must be introduced. This is not the case with an object literal due to it's fixed chain behavior.
Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype” property.
Other overhead work includes creating a new execution context, copying over additional properties, and even checking the return value. (In the posted case it also has to create a new one-off function object before it can even use is as a constructor which itself adds some additional overhead).
2 I'm sure there are counter-examples. But for such cases, I can only hope that the problem has been thoroughly benchmarked with all other bottlenecks identified and removed.