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).
Related
This question already has answers here:
Why do some array methods rely on the global Array object?
(3 answers)
Closed 1 year ago.
As far as I have seen any array related method it has to be accessed from its prototype, e.g. Array.prototype.slice.
Why is the from method called on Array object as in Array.from instead of being called as Array.prototype.from?
You can look at Array.from as a constructor for arrays. The important thing here is that it can create an array from both array-like structures (having array-like properties like indexes and .length) and also iterables (objects with .next() or in other words - having a registered iterator).
There is absolutely no point in having the .from() method attached to the prototype like [1, 2, 3].from(). What do you expect this method to do exactly in this context? It serves no purpose.
In general, the instance (prototype) methods manipulate a specific already existing instance of an array. Static ones like Array.from(), Array.of() and Array.isArray() don't (and shouldn't) require an instance.
This is true not only for arrays but for general class/prototype design especially in data-structures.
It's not in the Array.prototype because Array instances do not benefit from this method (it does not use any context). As to why it is on the constructor, that's purely convention. You could have the function floating around in the global scope e.g. ArrayFrom() but the specification groups related functions under their respective constructor as a convention and as sort of a namespace to avoid collisions.
Array.from is a static method that returns array, Array.prototype.slice is a method from the Array prototype and can be called on Arrays.
The reason is that JavaScript uses prototype chain: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
In general, when the method is not found in the instance, it looks into the prototype. If the method is not even there, it looks in the following prototype in the chain and so on. So this is why slice is found even if it is defined in the prototype.
The second reason is that the prototype is shared by all the instances of that class. So all the arrays share the same prototype - same object. Therefore the method doesn't need to be repeated in every instance and we save some space.
from(), on the other hand, is class method - you don't need instance to call that method. It is therefore defined directly on the Array class rather than on the prototype (because then it would be instance method).
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
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.
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
This returns a jQuery object. what is a jQuery object. Is it an object, an array, or some combination of both?
$("#id")
I'm looking in the source here, but can not find it.
First, what it's not.
A jQuery object is not an Array.
In JavaScript, there are built-in native constructor functions. One of these is Array. But ultimately the Array constructor creates Objects. jQuery objects are not built from the Array constructor.
So how is an Object different from an Array?
Since Object and Array are built-in native constructors, the objects created from the constructors have an internal [[Class]] property. You can see its value like this.
Object.prototype.toString.call({}); // [object Object]
Object.prototype.toString.call([]); // [object Array]
So you can see that these objects have that as a difference.
What other differences are there?
The prototype chain of the two objects are different. For a plain object, it could be visualized like this.
{} ---> Object.prototype ---> null
While for an Array, like this.
[] ---> Array.prototype ---> Object.prototype ---> null
So you can see that their inheritance distinguishes them as well.
So what about a jQuery object?
A jQuery object is more like a plain Object than an Array. But JavaScript lets you define custom (not built-in) constructors.
The toString value will be the same as an Object [object Object], but the prototype chain will be different.
function Foo() {
}
new Foo() ---> Foo.prototype ---> Object.prototype ---> null
So jQuery's prototype chain would be similar to this, but with the jQuery constructor instead of Foo.
So what does all this mean?
All objects in JavaScript are similar in that they inherit from Object.prototype *, but you can have different objects that have an extended prototype chain, and you can also have native objects that have an internal [[Class]] property that gives them distinction.
So to answer the question of "what type of object is a jQuery object", the answer is that it is an Object that inherits from Object.prototype like every object, but also inherits from the prototype of its custom constructor.
* Note that in ES5, you can also have an object that has no prototype chain. Its chain is terminated immediately with null.
But a jQuery object stores DOM elements at numeric indices, and has a .length property. Doesn't that make it an Array?
No, that just makes it an object with properties that are numbers, and a property named length.
var myObj = {};
myObj[0] = "foo";
myObj[1] = "bar";
An Array's properties are not special. They are identical to an Object's properties.
var myArr = [];
myArr[0] = "foo";
myArr[1] = "bar";
These two code examples are doing the exact same thing.
They're doing exactly the same thing? Really?
Well almost. The properties themselves are no different between Array objects and Object objects, but Arrays have some special behaviors.
For example, if I add a property at a higher index than the current .length accounts for, the .length will be automatically adjusted.
myArr.length; // 2
myArr[9] = "baz";
myArr.length; // 10
On an Array, .length itself has some "magic" abilities, like being able to truncate the Array by setting .length to a lower value.
myArr.length = 1;
myArr[1]; // undefined
So while a jQuery object has numeric properties and a .length property, it doesn't behave as a native Array would behave.
$() return an instance of the jQuery class (new jQuery()).
It therefore inherits all standard jQuery methods, as well as all plugins, from jQuery.prototype (which is aliased to jQuery.fn)
In addition, the jQuery() constructor turns each instance into an array-like object, by adding a lengthproperty, as well as indexed properties for each element in the set.
The returned object (see EcmaScript ยง4.2.1 on what that means) is an instance of jQuery's internal constructor function (jQuery.fn.init - see this answer for detailed information on jQuery's instantiation pattern), inheriting from the $.fn prototype object.
And of course, it is an instance of Object as nearly every object in JavaScript.
And, because every jQuery element represents a collection of [DOM] elements, it looks like an Array with its numeric index properties - although the length property isn't self-updating automatically, you can apply most of the Array methods on it. It is not a real Array instance (What's an Array, and what is in JS?).
jquery object is a object of jquery library basically all the jquery methods and properties are attached to that jquery object that you can;t use it as a normal javascript object. it also vary from which jquery object it is.