This question already has answers here:
How does jQuery makes the jQuery object both a function and an object property?
(3 answers)
Closed 7 years ago.
If $ is an object then how is jQuery able to call it with parenthesis (), like $('#MYdIV'). That is my first and most important question.
I am trying to learn design patterns, and underlaying mechanisms of creating an object. So I want to make library that when user type myLibrary({option1:true}); he would be able to instantiate an object without using keyword new.Just like jquery and this: https://github.com/bendc/animateplus/blob/master/animate.js
In this example he is not using keyword new nor this. He is just creating IIFE animate which returns another function with the same name. I don't know how is he able to do that. Is animate bound to global object?
jQuery or $ is just a function. Consider the following example which produces an object with the similar behavior.
Of course, jQuery has the much more complex and smart structure, this is just an example:
var not$ = function(o) {
var result = document.querySelectorAll(o);
result.customInnerText = function(text) {
if (text === undefined) {
return document.querySelector(o).innerText;
} else {
document.querySelector(o).innerText = text;
}
};
result.customClickHandler = function(callback) {
document.querySelector(o).addEventListener('click', callback);
};
return result;
};
not$.customConsoleLog = function(text) {
console.log(text);
};
not$("a").customClickHandler(function() {
var exampleText = not$("#title").customInnerText();
not$("#text").customInnerText(exampleText + "It works!");
not$.customConsoleLog(not$("p").length);
not$.customConsoleLog(not$("p")[0]);
});
Click me!
<p id="title">Example:</p>
<p id="text">Check!</p>
First a few terms:
a primitive is one of the following: string, number, boolean, null, undefined, symbol
An object is essentially any kind of thing that's not a primitve in Javascript. If it's a thing you want to use or manipulate, it's an object.
A function is a particular type of object that can be used to run javascript. This can be called by using the syntax function()
A constructor is just a function. It's a function which is intended to be called with the new keyword, as in new Thing(). Note the capital letter - that's convention.
So we can see that JQuery uses a function, not a constructor function. Specifically, if you look into the source code we'll find something like $ = function() {...}
And that's basically it - they define a global variable called $ and define it to be a function that can be used. Of course, since functions are objects, you can also do things like $.randomNumber = 4 without problems, and it won't affect JQuery in the slightest.
So if you're wanting to do something similar, you'll want to define your own global variable and set it as a function - just be aware of what's already taken - i.e. don't use $ or _ or whatever.
(1) $ is not an object, but a function.
console.log(typeof $);
// function
What might be confusing here - and this is just a guess - is that you can access properties on the $ variable, e.g. $.extend or $.fn (used when writing your own jQuery plugins). This is normal, as functions can have properties themselves. The ECMAScript specifications allow that.
(2) Constructor functions can be used to create new objects, but are not required. You can just used object literals, and that works just as well. As pointed out by #Jeff in the other answer, a function invoked with new makes it a constructor function. Otherwise, there is no difference in the syntax. It is up to you to pick whether you wish to use.
Related
Today while working my mind was stack at some point in javascript.
I want to know that what is basic difference between
function FunctionName(){
//Code goes here;
}
And
var MyFuncCollection = new Object();
MyFuncCollection.FunctionName = function(){
//Code goes here;
}
Both are working same. Then what is difference between then. Is there any advantage to use function with object name?
I have read Question. But it uses variable and assign function specific variable. I want to create object and assign multiple function in single object.
The first one defines a global function name. If you load two libraries, and they both try to define FunctionName, they'll conflict with each other. You'll only get the one that was defined last.
The second one just has a single global variable, MyFuncCollection. All the functions are defined as properties within that variable. So if you have two collections that try to define the same function name, one will be FuncCollection1.FunctionName, the other will be FuncCollection2.FunctionName, and there won't be any conflict.
The only conflict would be if two collections both tried to use the same name for the collection itself, which is less likely. But this isn't totally unheard of: there are a few libraries that try to use $ as their main identifier. jQuery is the most prominent, and it provides jQuery.noConflict() to remove its $ binding and revert to the previous binding.
The short answer is, the method in object context uses the Parent Objects Context, while the "global" function has its own object context.
The long answer involves the general object-oriented approach of JavaScript, though everything in JavaScript is an object you may also create arrays with this Method.
I can't really tell you why, but in my experience the best function definition is neither of the top mentioned, but:
var myFunction = function(){};
It is possible to assign function to variables, and you may even write a definition like this:
MyObject.myMethod = function(){};
For further reading there are various online Textbooks which can give you more and deeper Information about this topic.
One main advantage I always find is cleaner code with less chance of overwriting functions. However it is much more than that.
Your scope changes completely inside the object. Consider the following code ::
Function:
function FunctionName(){
return this;
}
FunctionName()
Returns:
Window {top: Window, location: Location, document: document, window: Window, external: Object…}
Object:
var MyFuncCollection = new Object();
MyFuncCollection.FunctionName = function(){
return this;
}
MyFuncCollection.FunctionName()
Returns:
Object {}
This leads to some nice ability to daisy chain functions, amongst other things.
The first:
function functionName (){
//Code goes here;
}
Is a function declaration. It defines a function object in the context it's written in.
Notice: this doesn't have to be the global context and it doesn't say anything about the value of this inside it when it's invoked. More about scopes in JavaScript.
Second note: in most style guides functions are declared with a capitalized name only if it's a constructor.
The second:
var myFuncCollection = {};
myFuncCollection.functionName = function () {
//Code goes here;
};
notice: don't use the new Object() syntax, it's considered bad practice to use new with anything other then function constructors. Use the literal form instead (as above).
Is a simple assignment of a function expression to a property of an Object.
Again the same notice should be stated: this says nothing about the value of this when it's invoked.
this in JavaScript is given a value when the function object is invoked, see here for details.
Of course, placing a function on an Object help avoiding naming collisions with other variables/function declarations in the same context, but this could be a local context of a function, and not necessarily the global context.
Other then these differences, from the language point of view, there's no difference whatsoever about using a bunch of function declarations or an Object with bunch of methods on it.
From a design point of view, putting methods on an Object allows you to group and/or encapsulate logic to a specific object that should contain it. This is the part of the meaning of the Object Oriented Programming paradigm.
It's also good to do that when you wish to export or simply pass all these functions to another separate module.
And that's about it (:
I've looked at various answers on SO that answer similar questions, but none have really answered what I'm looking for. Examples here:
jQuery prototype and constructor function chaining
How does basic object/function chaining work in javascript?
I'd like to be able to chain methods from a function, but also use that function as a namespace. You can use the jquery object as a function like so:
$('selector');
but you can also reach methods straight from the $ variable, like so:
$.ajax(
How is this achieved? I've tried looking into the jquery source but it's near impossible to follow.
In Javascript functions are first-class objects. In particular, they are objects.
var greet = function(name) {console.log("Hello, " + name + "!"); };
greet.lang = "English";
Is legal. Then the following are both valid:
greet("Alice"); // prints Hello, Alice!
console.log(greet.lang); // prints English
I don't think it's accurate to call $(...) a constructor. In Javascript the line between constructor and function is blurred, but usually I would say a constructor is used with new, and, by convention, starts with a Capital letter. $ is simply an object, and in particular one that is a function, so may be called, and has other properties that may be accessed.
I also wouldn't call $, or in my example greet, a namespace. You may be thinking of the package syntax in Java where com.mycompany.util.StringFunctions would have the package/namespace com.mycompany.util, or in C++ where this might be written as MyCompany::Util::StringFunctions. Javascript doesn't quite have this concept, but in more or less any OO language it can be simulated with objects, as above. I would say $ just feels like it's a namespace because it's a rather huge library, but it's a huge library that is implemented as one object that is also a function, with many properties.
Just try this:
var foo = function (){
alert ("I'm a function beep beep");
};
foo.bar = "This is a string";
foo.otherFoo = function (param) {
alert ("I'm also a function blup blup"+param);
};
Then you can call the first function foo(), the variable foo.baror the second function with a value foo.otherFoo(" and more blup.")
How do I create custom syntax/prefix for my functions?
jQuery uses $.function, is there a way I can do that, so say $$.myFunction() works?
That syntax is just a method call on an object:
var $$ = {
myFunction: function () {
return "hello";
}
};
$$.myFunction(); // hello
jQuery is just relying on a global object called $ which contains multiple functions.
It can do this because $ is a valid identifier.
You could quite easily do
var $$ = {
myFunction: function() {
console.log("Foo");
}
};
$ is just a variable name.
var $$ = {
myFunction: function () { ... }
};
… but don't use $$. $ is a stupid variable name that tells people reading the code absolutely nothing about what it does. $$ has the same problem.
$$ = function() {
};
$$.myFunction = function() {
};
So all of these answers are correct, but none really explains the "why" . . . the "syntax/prefix" that you are talking about is called a "namespace" and the majority of the time that you see it, it is because there has been a JavaScript object that has been defined with a set of methods defined in it.
Some common examples:
Math.round() - references the round function within the JavaScript Math object
$.trim() - references the trim function for Jquery (which, by default, uses the $ namespace)
Those are the "object forms" of namespacing, but you also pretty regularly see the "object instance" forms as well. For example:
var myDate = new Date();
myDate.getFullYear();
In that example, myDate is an instance of the JavaScript Date object, so, by calling myDate.getFullYear();, you are really namespacing that function to that specific instance of the Date object, rather than the object itself.
So, to answer your question, if you would like all of your functions to be namespaced, the easiest way to do that is as others have shown . . . create a JavaScript object and make your functions methods of that object.
More on namespacing here: http://addyosmani.com/blog/essential-js-namespacing/
Other than tricking existing functions that already implement this as something, why would you want to write a javascript function so that you need to alter its context (via .call or .apply) rather than explicitly passing the "context" as another parameter? Is there a performance benefit?
Example:
function tryIncrement(inc, context) {
context = context || this; // just so we can reuse same fn for the example
if( typeof context.val!= typeof 1|| typeof inc != typeof 1 ) return false;
context.val += inc;
return true;
}
var a = {name: 'A', val: 5}, b = {name: 'B', val: 20};
// reassign internal context
for(var i = 0, n = [1,3,"not a num",5]; i < n.length; i++) {
if( tryIncrement.call(a, n[i]) ) console.log('incremented', i, n[i], a);
else console.log('failed to increment', i, n[i], a);
}
// provide explicit context;
// could just as easily declared function so context was first param
// so it looked the same as previous implementation
for(var i = 0, n = [1,3,"not a num",5]; i < n.length; i++) {
if( tryIncrement(n[i], b) ) console.log('incremented', i, n[i], b);
else console.log('failed to increment', i, n[i], b);
}
There are many cases where you may wish to use this instead of passing an extra parameter. Consider the following function for example:
Function.prototype.async = function () {
setTimeout.bind(null, this, 0).apply(null, arguments);
};
This function allows us to defer a function call as follows:
alert.async("This will display later.");
alert("This will display first.");
You can see the demo here: http://jsfiddle.net/AjwQu/
Instead of binding the function to this we could have passed it as a parameter instead:
function async(funct) {
setTimeout.bind(null, funct, 0).apply(null, [].slice.call(arguments, 1));
}
We would use it like this now:
async(alert, "This will display later.");
alert("This will display first.");
The result is the same: http://jsfiddle.net/63dBF/
However to get the arguments we have to use [].slice.call(arguments, 1) instead. In the first example we could simply use arguments as the function was not a part of the argument list.
Everything has it's advantages and disadvantages. You just need to know what to use when. Hope this helps a bit.
Bonus: It's really easy to convert a function that uses this into a function that accepts an extra parameter and vice versa. First let's define a few utility functions:
var functProto = Function.prototype;
var bind = functProto.bind;
var bindable = bind.bind(bind);
var callable = bindable(functProto.call);
var appliable = bindable(functProto.apply);
The bindable function allows you to create a bindable version of an existing function which when called returns a new function bound to the given arguments.
The callable function allows you to create a callable version of an existing function which when called calls the existing function with the given arguments and this pointer.
The appliable function allows you to create an appliable version of an existing function which when called applies the given arguments and this pointer to the existing function.
Then given the function in the first example we can create the function in the second example as follows:
var async = callable(functProto.async);
See the demo here: http://jsfiddle.net/3dSBS/
Similarly we can convert the function in the second example into the function in the first example as follows:
Function.prototype.async = function () {
return async.apply(null, [this].concat([].slice.call(arguments)));
};
See the demo here: http://jsfiddle.net/rJQyS/
As you can see it's much easier to write a function using this and then construct the function accepting the context as a parameter from it than the other way around.
As far as I can tell the use of this isn't really any different than
another parameter, it just has a more complicated way of being
modified.
I think the easiest way to answer your question is to imagine if the creator of the base Javascript language had followed your conventions.
A world without this
A world without this is a scary noisy place with lots of excessive duplication:
var arr = [1,2,3,4];
arr.reverse(arr); //4321
More opportunities for misleading or verbose syntax
var str = "stringtobesplit";
"abiglongstringnotbeingsplit".split(str,":");
String.prototype.split(str,":");
And its not at all rid of apply at least:
Math.max.apply(arr); //didn't add the initial `this` since it doesn't exist
Effectively there would be a choice between creating only global functions, or creating functions on prototypes or objects that made assumptions about the types of the arguments it was receiving but didn't enforce those assumptions. For instance imagine the toString method in our fantasy world.
You could either create a global toString method which would take in an object of every type ever, and try to make them all work, or you could have a function on the prototypes of each type as it works currently, with no enforcement that it would be called on that type. Someone could call
Array.prototype.toString(str)
And we would need to handle it gracefully (for what its worth doing this with apply seems to revert to the Object.prototype.toString and returns [Object String]). So we would need to identify the correct prototype method to call in those cases, which means my guess is that the convention would be to call
str.toString(str)
or something along those lines.
So whats the point?
this is built to handle the common case for javascript methods on the prototype chain. It gives us a shorthand to allow an object to act on itself without duplicating the call to it or having to know exactly what its prototype is. Without it, we would either have to have no functions on objects, or would have to explicitly call the function on itself every time, introducing extra syntax and potential errors.
call and apply are the exception cases, and apply at least would have uses even if this went away. Its never a good idea to write your apis to the exception cases. If you're creating object oriented code, you should use this as an easy way to refer to the object that is the context for the call. If you write this well, then call and apply should be used rarely and in special situations.
TL;DR - this was designed as part of Javascript for a reason, use it when you're creating methods on objects for more clear and understandable syntax.
When you do object oriented programming your functions WILL depend on the context and it does not make sense do provide it as a parameter, as this would deafeat the purpose of object oriented programming.
It also makes sense to provide an implicit context for callbacks. You do not have to remember the correct order of the parameters if you only need the context. You would not have to use parameters at all in that case. So instead of
function mayCallback(param1, param2, context)
you could just write
function myCallback()
and use this, if you do not need param1 and param2.
To address my main purpose -- is there a performance benefit using this over a function parameter? -- the answer seems to be no:
http://jsperf.com/function-context-vs-parameter
Although there seems to be a slight benefit (may not be significant, however) around using parameter values instead of instance (this) variables within objects.
(Please test for yourself and comment if it's different)
Regarding the purpose being addressed by the other answers: there are some neat use cases as pointed out by #Aadit, maintainability is debatably a personal preference, but like #ben336 said if you're working with Objects (and thus OOP) then this can be more useful.
The ECMAScript 5th-edition native function bind may be an interesting bridge between the two worlds, or at least a time-sucking tangent to explore.
The instance vs parameter values test referenced above may also be a good example of my point -- if you're building a static library of functionality, you can "hijack" obj.callback2 by scoping to a different this, or just call obj.callback directly on your alternate context.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can jQuery behave like an object and a function?
In jquery we can use $ as a function as well as a namespace. for example both of these use-cases are valid.
$("div").html("<b>Wow!</b> Such excitement...");
var trimmed = $.trim(someString);
How can one identifier $ act as an object as well as a function at the same time?
First things first: jQuery (or its alias $) is a function. This is very important because functions are "first-class" objects in JavaScript. And since they are objects themselves, they have the ability to be given properties and methods just as any other object. For example:
var f = function() {};
f.h = function(x) {
console.log(x);
};
This is what allows jQuery to work its magic. In addition, through the use of inheritance, we have the potential to chain methods like you show in your first example. $(selector) returns a jQuery "interface" (technically [object Object]) based on the value of selector which, off of which, we can run methods such as .html, .css, and .toggle to name a few.
It is not.
$ is only a function.
It has prototype functions as well which can be used, since a function can have other function as a part of it (since a function is an object in and of itself).
You can do:
console.log( Object.getOwnPropertyNames($) );
to see all of the attached functions (and properties).