Why do class/function constructors in JS evaluate strings as expressions? - javascript

I took a look at one of the rules from eslint-plugin-security and found that user input could in theory lead to a Remote Code Execution bug.
const a = class {};
console.log(a['constructor']);
a['constructor']('console.log(1)')();
function b() {}
console.log(b['constructor']);
b['constructor']('console.log(2)')();
const c = {}
console.log(c['constructor'])
console.log(c['constructor']('console.log(3)')());
From the snippet it's easy to see that constructors of classes and functions seem to parse strings and evaluate them as valid code. Objects for some reason don't exhibit this behaviour.
Why is this even allowed to happen? What feature of JavaScript needs this behaviour from function/class constructors? I'm assuming it's integral to the way JavaScript works otherwise I don't see why it hasn't been removed from the language.

The problem is that the .constructor of a class is Function, and calling the Function constructor with a string creates a function from that string, and then calling that function results in the string's code being executed:
const a = class {};
console.dir(a['constructor'] === Function);
a['constructor']('console.log(1)')();
This isn't really any different from
Function('console.log(1)')();
It's just that a class's constructor property happens to point to the same thing.
Objects can exhibit the same property, if you navigate up to the .constructor property twice (first one accesses the Object constructor, second accesses the Function constructor):
const a = {};
console.dir(a['constructor'].constructor === Function);
a['constructor'].constructor('console.log(1)')();
If you allow arbitrary access to properties of any object, and also allow those properties to be called with arbitrary arguments, pretty much anything can be executed. The prototype chain (and .constructor) properties are useful, but like many things, they can be misused.

Related

Can you initialize a function? - Javascript

I have this function here, I need to work with this other function called OrderRepository in another file.
main.js
function main() {
var orderRepo = new OrderRepository();
// Your code here
}
orderrepository.js
function OrderRepository() {
}
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [{ array of objects }],
return yesterdaysOrders;
};
These were given as examples to use, 1 question rolled into 2 parts:
1) var orderRepo = new OrderRepository();
Can you initialize a function like this?
2) In the orderrepository.js:
function OrderRepository() {
}
is being called in main.js, but nothings inside of it, this was given as-is in the assignment, is this just a typo and really they meant to throw everything inside that function or am I missing something?
Shouldn't it look like this?
Expected
function OrderRepository() {
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [{ array of objects }],
return yesterdaysOrders;
};
}
Diving deeper into JavaScript, the language is hard to understand. JavaScript is not really OOP (imho), at least it does not implement the common OOP concept. Some call it object-based language. There are no classes. Recent ECMA Script standards do implement the class keyword, however, it is syntax sugar. Used with the new keyword it builds the same objects as you can achieve by 'constructor' functions.
Everything in JavaScript is an object, even numbers and functions. Every function can act as constructor function. The new keyword call a constructor function with a newly creates empty object as the function's this context. The function can do what it wants. If it does not return anything, its this context is returned by the new expression.
Since there are no classes, there is no inheritance. Some inheritance-like behavior is achieved by the prototype concept. In most cases the constructor will return nothing and sometimes modify the this object by adding properties. Methods are properties holding a function object. The object in the new context of a constructor call will have a prototype object reference as the __proto__ property. This is copied by the new operator from the prototype property of the called constructor function. The default is an empty object.
// empty constructor function
function OrderRepository() {
}
// define a function property on the constructor's prototype object
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [ /* array of objects */ ],
return yesterdaysOrders;
};
// create an empty object with a `__proto__` property holding a
// reference to the object { getYesterdaysOrders: function(){/*code*/} }
var obj = new OrderRepository();
Now, when the method invocation obj.getYesterdaysOrders() is tried, JavaScript will look if there is such a property defined in obj. If not, it looks if there is a reference in obj.__proto__ and the property name is searched the properties of obj.__proto__. If not, the same step is repeated until it was found or the __proto__ property in the chain is null. Since obj.__proto__.getYesterdaysOrders is defined, it is checked if it is a callable function object and finally invoked with a this context of obj since we called obj.getYesterdaysOrders(). Otherwise an error is thrown.
NOTE: Even if the major browsers do expose the __proto__ property, it is not part of the standards. Do not use it directly (except for debugging at development time) and even more important: do not manipulate it. If you really need to get or manipulate a prototype (__proto__) of an object instance after construction, use the methods of the builtin Object object.
Upon your last edit: Your expected code would define a new function object in prototype on each instantiation (and thus constructor invocation). This is not what you want, it's just needless overhead.
Regarding the first part, it looks like this assignment is dealing with how to create instances of objects in JavaScript as that is what the new operator does.
You can find more information regarding new on the MDN.
Regarding the second question, it is dealing with how to create objects that inherit methods. So, yes it is empty, until you get to the prototype expression.
The expected code would not give you the inheritance in this case. Notice how OrderRepository is repeated inside the function, which would be invalid. Javascript requires you to add inheritance to the special prototype property. Code that is added to the function declaration, would be scoped to the function only in that case.
You can find more information about prototype on the MDN.

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.

Why are JavaScript function objects allowed to differ from the string to value map format?

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.

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.

Is there a performance advantage in using an object literal over a self instantiated constructor?

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.

Categories