MDN says it is "an Array like object" but does not say what it is an instance of.
It is not an HTMLCollection or NodeList.
If I call Object.prototype.toString.call(arguments) it returns "[object Arguments]" but arguments instanceof Arguments is an error.
So what is arguments an instance of?
So what is arguments an instance of?
It's an instance of Object. There does not appear to be any public Arguments constructor that you can use with instanceof to identify it that way.
If you want to uniquely identify it, then:
Object.prototype.toString.call(arguments) === "[object Arguments]"
is a safe way to identify it.
Per section 9.4.4 in the EcmaScript 6 specification, the arguments object is either an ordinary object or an exotic object. Here's what the spec says:
Most ECMAScript functions make an arguments objects available to their
code. Depending upon the characteristics of the function definition,
its argument object is either an ordinary object or an arguments
exotic object.
An arguments exotic
object is an exotic object whose array index properties map to the
formal parameters bindings of an invocation of its associated
ECMAScript function.
Arguments exotic objects have the same internal
slots as ordinary objects. They also have a [[ParameterMap]] internal
slot. Ordinary arguments objects also have a [[ParameterMap]] internal
slot whose value is always undefined. For ordinary argument objects
the [[ParameterMap]] internal slot is only used by
Object.prototype.toString (19.1.3.6) to identify them as such.
Since it is an "exotic" object, that essentially means it doesn't follow all the normal and expected conventions. For example, there is no constructor function from which you can create your own object. And, because there is no public constructor function, that probably also explains why there's no instanceof that you can test on it to uniquely identify it.
You can retrieve the name of the function where arguments returned from using callee.name
function test() {
this.args = arguments;
}
var obj = new test();
console.log(obj.args.callee.name);
function test() {
return arguments
}
console.log(test().callee.name);
See also Why was the arguments.callee.caller property deprecated in JavaScript? , Arguments object
Related
So as long as anything in Javascript is actually an object, what makes an object behave as a function? What internal properties and labels make an object behave as an object we can call instead of just using it to store values?
There is an internal property, [[Call]], that determines what will be executed, when the object is called.
Plain objects don't have this interal property, so they aren't callable, and can't be made to be callable.
The only callables in JS are functions (which are also objects), classes (which are actually functions, and therefore objects as well), and Proxy objects that wrap callables.
To create a callable object, create a function, and make it have the properties and prototypes you would like.
So as long as anything in javascript is actually an object
Well, not everything in JavaScript is an object. For instance, primitives such as strings, booleans and numbers are not objects. JavaScript just wraps these primitives in objects when properties are accessed.
what makes an object behave as a function what internal properties and
labels did this job to make an object behave as an execution code
instead of just storing variables
You're correct about functions being objects, however, unlike regular objects which just store key-value pairs, function objects have a special internal method which they implement known as [[Call]]. This call method is what executes the code associated with the function object and is invoked when you call a function (func_name()). So, any object which implements the internal [[Call]] method is callable. You yourself cannot make an object callable by implementing this property as it is not part of the ECMAScript language itself, but rather a method name used by the spec. Instead, we use the function keyword for that. Function objects are still objects at the end of the day, so you can assign properties to them as well as access preexisting properties:
function foo(a) {
return a;
}
foo.bar = "foobar";
console.log(foo.length); // able to access pre-existing properties
console.log(foo.bar); // able to access our own properties
console.log(foo(2)); // able to invoke (due to [[Call]])
You can read more about function objects here
You could assign an object to a function to get a callable function.
var object = { foo: 42 },
callable = Object.assign(function () {}, object);
console.log(callable)
console.log(callable())
console.log(Object.keys(callable));
You can't make an object callable.
You can add properties to an already existing Function object though. You will still retain call() behavior, but can also get and set properties.
var object = { increment: function(x){
return x+1
} ,
foo: 'foo'
};
var decrement = function(x){
return x-1
}
callable = Object.assign(decrement, object);
console.log(callable.increment(12)) //13
console.log(callable(67)) //66
console.log(Object.keys(callable));//[ 'increment', 'foo' ]
There are different prototypes in javascript. E.g. Object.prototype, Function.prototype, Array.prototype. Javsacript works based on prototypical inheritance. This defines what is the type of any object.
When you create a function, its __proto__ (also called as "dunder proto") is set to Function.prototype. Basically a function inherits from Function.prototype which in turn inherits from Object.prototype. Following example is taken from MDN. (Note - I think __proto__ is not standardized. Object.getPrototypeOf should be used)
function f() {
return 2;
}
// Functions inherit from Function.prototype
// (which has methods call, bind, etc.)
// f ---> Function.prototype ---> Object.prototype ---> null
MDN has a great explanation for prototypical inheritance. For more information read this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
When you do a "typeof" on both of these types you get "function" for functions and "object" for objects, but isn't it so that functions are special objects, if so what are the properties that differentiate a function from an object?
When you do a "typeof" on both of these types you get "function" for functions and "object" for objects,
First of all, the specification for typeof is basically just a lookup table, where it says "if the value is a function object, return the string "function"). So it doesn't provide the real data type of the value (which would be object for functions).
but isn't it so that functions are special objects
Yes. Functions are so called callable objects.
Objects have, in addition to "normal" properties, so called "internal" properties. You can think of these as some kind of internal state, that needs to be maintained for the object to work correctly, but that is not accessible in user code.
Some of these internal properties make certain objects special because not every object has them. One of them is [[Call]] (internal properties are denoted with double brackets), which contains code in some implementation-specific format.
When you call a value (i.e. foo()) the interpreter first checks whether the value is an object and then checks whether it has an intern [[Call]] property. If yes, then the code stored in that property is executed.
Here is a very rough example of how this could look like internally:
// Simulates a function call implementation, i.e. what happens when
// you do `foo()`
function call(value) {
if (typeof value !== "object") {
throw new Error('Not an object');
}
if (!value["[[Call]]"]) {
throw new Error('Not a function');
}
return eval(value["[[Call]]"]);
}
// Simulated function object that has a name ("normal" property)
// and the internal property [[Call]].
// This would be the internal representation for something like
// function func() {
// console.log('some code');
// }
var func = {
name: "func",
"[[Call]]": "console.log('I\\'m a function!');",
};
call(func);
Side note: If you know Python, then this concept should be familiar to you, because Python allows you to make arbitrary objects callable by implementing __call__.
In addition to [[Call]] there is also [[Construct]]. We actually distinguish between callable and constructable functions. Constructable functions are those that can be invoked with new. Functions created via function ... are both callable and constructable. Arrow functions are only callable, functions created via class ... are only constructable. And this distinction is made based on whether [[Call]] or [[Construct]] or both are set.
if so what are the properties that differentiate a function from an object
In addition to these special internal properties, function objects also have all properties defined on Function.prototype:
console.dir(Function.prototype);
// etc
(and Function.prototype "extends" Object.prototype) which is where .call and .apply are defined, but these alone do not make functions special. The internal [[Call]] property is what makes them special.
The same applies to other built-in "classes" such as Array, Date or RegExp. All instances of these classes have additional methods/properties that are defined on Array.prototype, Date.prototype, etc.
Functions (which are first-class objects) can be called, while other objects cannot.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions for more detail.
I am a little confused with Array.from() in JavaScript. I know/think that is turns array-like values into arrays, but why, if Array is an object, do we not have to use the 'new' keyword to instantiate it before we can use it?
JavaScript has several collection types (HTMLCollection, NodeList, FileList, 'arguments', etc). The latter one being the variable containing all arguments passed to a function.
Imaging you have a function that requires data to be passed using an ordinary array - in that case Array.from(..) is super useful to convert any of the other collection types.
Array is a function, functions are objects, objects have properties. from is just a property on that object. That fact that Array is a function and can be invoked with new is irrelevant.
Example:
function foo() {}
foo.bar = function() {
console.log('hi');
}
foo.bar(); // hi
Presumably the primary reason for adding from as property to Array is to namespace it (instead of creating another global function).
I have been going through Javascript Koans when I hit upon the part about inheritance. I became deeply fascinated and spent the entire morning researching how inheritance works in JS.
I understand that a function can be used to execute code which is declared in its code body, and a function can also serve the purpose as a constructor for objects which inherent from that functions prototype object.
It seems as though functions have two purposes that are not at all related- the ability to create objects, and the ability to execute it's declared code. Is there any relationship between these two abilities?
An attempt at a simple answer (with some approximations to try and keep it simple)
You could see a "class" function both as the constructor of the underlying object and the place where its methods are defined.
Construction
The new operator will create an empty object whose type will reference the function and bind it to this, then call the function.
The function may set some properties of this, which will become values for the new instance properties.
Methods
In JavaScript almost everything, notably functions, can have properties.
Among these, the conventionally named prototype property is the container of all class methods (and possibly other property values).
function Guy (name) { this.name = name; }
Guy.prototype = {
sayHello: function () { console.log ("Hello, I'm "+this.name; }
}
the Guy method sayHello is literally the property Guy.prototype.sayHello, which happens to be a function.
You could just as well add values instead of functions to the prototype property, which would act as class variables (of sorts).
So let's create an object Bob from the function/class Guy:
var Bob = new Guy("Bob");
Bob.sayHello();
when you invoke Bob.sayHello(), the virtual machine will first look for a Bob.sayHello property (which usually does not exist), then for a Guy.prototype.sayHello (and would go up the inheritance chain or die trying, but that's another subject), then bind this to Bob and call Guy.prototype.sayHello, which will be able to access the Bob instance through this.
As an illustration of the mechanism, you can break the prototype chain for a given object instance:
Bob.sayHello = function () { console.log ("my real name is Robert"); }
The duality you're describing doesn't in fact exist. Functions exist to be executed. But, in JavaScript, functions are also objects, so they can have properties such as prototype. (You can add other properties to your function and use them from its body as a means of making it "stateful".) From the function's point of view, prototype is just another ordinary property.
Object construction is the domain of the new operator. What it does, is this:
it creates an empty object,
it creates a hidden, non-modifiable binding between the created object and its constructor, which is then used to look-up a property value on its prototype whenever a property doesn't exist on the object itself,
it executes the provided function in context of that object (this points to it during that function's execution), and
it returns either the created object (if the provided function returned undefined) or the return value of the provided function.
(The {} notation for creating objects is just a shortcut for new Object().)
Additional note on prototypal inheritance (that is used in JavaScript): The second step in the above sequence has an important result. Any object in JavaScript has a constructor ({} has Object as constructor), so setting an object as the value of prototype property of your function doesn't just create a single binding. It transitively creates a "prototype chain". Any property is then looked up first on the object, then on its constructor's prototype, then on it's constructor's prototype's constructor's prototype, etc.
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.