I've been using JavaScript for a few years now in web design/development, and everything I know has been self-taught (I was a design major and hobbyist front-ender turned full web developer in pursuit of my career). With that background, I discovered something that I want to learn more about and have no idea what it is called, how it works, or that it may even be something extremely simple.
I've tried to search for more information about this (to prevent myself from needing to ask this), but it's difficult when I'm not sure what it's called that I'm even looking for...
I noticed in a few JavaScript libraries that I use that a variable name can be both a function and an object. For example, the jQuery library uses the name "jQuery". When logged using typeof jQuery
it is a function, and typeof jQuery()
is an object. What is interesting to me is that initial thought would suggest that jQuery()
would be a function but it's actually an object.
//jQuery:
ƒ (a,b){return new r.fn.init(a,b)}
//jQuery():
r.fn.init {} //Expanding this reveals functions inside of __proto__ (which is obviously a clue, but I need more info)
When I try to do something like this I end up overwriting the name (as I would expect):
//Declare an object:
var planetEarth = {
'sky': 'blue',
'grass': 'green'
}
//Now overwrite the object as a function:
function planetEarth(){
console.log('inside of a function now');
}
This is understandable within the realm of JavaScript, so my question is how does a library like jQuery pull off having both at the same time?
Ultimately (using the above example) I would like to be able to do something like this:
planetEarth().sky; //"blue"
So my roundabout question is simply what is this called?
And a follow-up of where can I learn the basics of accomplishing this?
I've found resources on object-oriented JavaScript and classes, as well as prototypes, but I'm not sure if either (or both) of those concepts are what this is. All of the articles I've found aren't starting at the beginning and seem to always jump into unnecessarily complex examples. I'm not looking to make a giant library- I just want to get some more experience at the very basic level. Again, this could be embarrassingly simple and I've just never come across the concept before, so I appreciate being pointed in the right direction, thanks.
First-Class Objects
In Javascript, functions are first-class objects. This means that functions are just another kind of object. You can put a function in a variable, you can return a function, you can make an array of functions, and all that. Functions are objects.
Consider a slight change in your attempt:
You mention that you would like to use
planetEarth().sky
, but observe that whileplanetEarth
is a function (and an object, as I said),planetEarth()
is the result of callingplanetEarth
with no parameters. Therefore, whether you can or can't doplanetEarth().sky
does not depend onplanetEarth
as an object having thesky
field, but rather depends on whatever you return fromplanetEarth
having that field.Bonus: did you know that functions can be declared very much like "normal" variables? See below:
Perhaps looking at the code above will help you clear the confusion. The function is
myFunc
.myFunc()
is simply the act of calling that function. Iftypeof myFunc()
givesfunction
, it is just a coincidence that the object thatmyFunc
returned happened to also be a function.jQuery is a function. Properties can be assigned to a defined function.
Every JavaScript function is also an object, just as every array is also an object. I don't think there is a special name for this, it's just how the language works.
You may be confusing two different things: what a function returns when you call it, vs. the function itself. Take your example:
This code does not rely on the function
planetEarth
being an object and having any properties. You're calling the function, so to make this code work the function would need to return an object.Because a function is an object, you can also set properties directly on the function itself. The code below uses both of these features. This version of
planetEarth()
returns an object withsky
andgrass
properties, so it works as in your example: you call the function to get an object with those properties.The code also sets an
exists
property directly on the function, and you can access that property without calling the function:jQuery makes use of both of these facilities.
jQuery
is a function that you can call. It returns a value commonly called a "jQuery object". That object has properties and methods, such asjQuery('#foo').show()
. It also has "array-like" properties that you can access as you would any array, e.g.jQuery('#foo').length
andjQuery('#foo')[0]
. ThejQuery
function adds those properties to the value it returns.At the same time, the jQuery library adds other properties and methods to the
jQuery
function itself. You access without calling the function, e.g.jQuery.ajax({...})
.A couple of other notes to help you understand the jQuery code. First, download the uncompressed version of jQuery. It looks like you are studying the compressed version, which has shortened names that won't make any sense.
Also, if you are wondering what
jQuery.fn
is, it is simply an alias forjQuery.prototype
. Whenever you seejQuery.fn
you can mentally substitutejQuery.prototype
; learn how JavaScript prototypes work and you will understandjQuery.fn
.And now you may wonder why
jQuery.fn
exists at all. Why not usejQuery.prototype
directly like other JavaScript code that uses prototypical inheritance? In fact, you could, and it would work the same asjQuery.fn
. But the very first version of jQuery, back in 2006, didn't work this way.jQuery.fn
was its own separate object, and every time you called thejQuery
function, it copied all of the methods and properties from this object into the value it returned.As you can guess, this was rather inefficient, so jQuery was changed to use
.prototype
so it could return an object that inherits all the methods such as.show()
and.hide()
instead of copying them all one by one. At the same time,jQuery.fn
was kept around as an alias forjQuery.prototype
to avoid breaking existing code.This is a silent answer...
This is how jQuery does it.
f
is a function but when it gets called it returns an object.Interesting part: function is also an object.
f instanceof Function
andf instanceof Object
are both valid. So, you can call a variable as a function and / or assign some properties because it is also an object.