I am assuming that $('thing1') or document.getElementById('thing1') will return the node or object representing <div id="thing1"></div> But how do I access that in myFunc()?
HTML:
<div id="thing1"></div>
JS:
var foo = $('#thing1').myFunc();
var myFunc = function() {
console.log(this); // I want to log $('#thing1')
}
I am trying to figure out how various api's work, take highcharts for example, they do something like this:
$('#dailyKPIChart').highcharts({
chart: {
zoomType: 'x',
spacingRight: 20
}
});
And the chart will load in $('#dailyKPIChart')
How does that work?
There is no way to (programatically) know which variable (or which function call) was used to get the object upon which a method was called.
A debugger will tell you (set a break point, and then look at the stack) but that won't be useful if you think you need to know the name in your code.
$a_jquery_object.selector will (in older versions of jQuery) hold the selector used to construct a jQuery object, which might help for your particular example.
And the chart will load in $('#dailyKPIChart')
How does that work?
It doesn't need to know about $() or '#dailyKPIChart', it only needs the object that you get when calling it, which is available through this, which your earlier example code already uses.
There are several ways to invoke a function in javascript and perhaps you are after call (or its cousin apply):
Supposing you define your funciton as:
var myFunc = function() {
console.log(this); // I want to log $('#thing1')
}
You can call it while at the same time you specify the context. For example, you can do this:
var foo = $('#thing1');
var myFunc = function() {
console.log(this);
}
myFunc.apply(foo);
Or via call:
var foo = $('#thing1');
var myFunc = function() {
console.log(this);
}
myFunc.call(foo);
If you have arguments to pass, you can do so by specifying an argument list or an array of arguments. For example:
var foo = $('#thing1');
var myFunc = function(one, two) {
console.log(one);
console.log(two);
console.log(this);
}
myFunc.apply(foo,[2,3]);
Or with call:
myFunc.apply(foo,2,3); //foo is the calling context
Fiddle
Related
I was wondering how does JQuery use "$" both as a function to return a new instance and an instance itself.
I guess that it's not exactly the case but I mean, we can use $(element).method and for exemple $.ajax without brackets (.ajax will still be a method).
EDIT :
I think that I misspoke. I know how objects work in JavaScript and my question was not about that.
JQuery allows us to use $ without the key word new. It has a function that returns a new instance automatically. So my question was about how it can use $ both as a function to instanciate a new object and an object itself.
Let's say we have
(function() {
var jQ = function (arg){
this.own = arg;
};
jQ.prototype = {
foo : function (){
alert("Foo");
},
bar : function (){
alert("Bar");
}
};
window.jQ = window.$ = jQ;
return jQ;
}());
In this exemple, i have to go througth the key word new if I want to use my object.
So how does JQuery do to avoid us this step ?
Function is an object in javascript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function You can check this code:
var f = function () { alert(1); };
f.func1 = function () { alert(2); };
f.func2 = function () { alert(3); };
and you can call f(), f.func1() and so on...
It's not jQuery. In JavaScript functions are objects.
In the case of $(element).method you are passing a parameter element into the jQuery function, where with the $.ajaxcall you are calling the ajax function inside of the $ jQuery object. In both cases we are talking about the same piece of code, but we are using it two different ways.
Have a look at the raw source code for jQuery and that should help to visualize this a little: https://code.jquery.com/jquery-2.1.1.js
Note: the jQuery function that is used repeatedly is aliased at the bottom of the page.
Remember that in JavaScript, functions are objects. So, using the specific functions you called out in your question, you could create them like this:
var $ = function(selector) {
...
};
$.ajax = function(url) {
...
};
EDIT: To respond to your edited/clarified question, you don't have to use prototyping to make constructor functions in javascript. Remember, all a constructor is doing is returning an object - here's the equivalent of your prototyping code, but without having to use the new operator to instantiate the object:
(function() {
var jQ = function (arg){
return {
own: arg,
foo: function (){
alert("Foo");
},
bar: function (){
alert("Bar");
}
}
};
window.jQ = window.$ = jQ;
return jQ;
}());
I believe this style is actually preferred by Douglas Crockford because forgetting to use the new keyword won't throw an error but you'll get some very unexpected behavior.
JQuery allows us to use $ without the key word new. It has a function that returns a new instance automatically.
Nothing magical here. The jQuery function simply returns an instance of another constructor (source):
// Define a local copy of jQuery
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init( selector, context );
},
The only magic going on in the code (not shown in the example) is that jQuery.fn.init.prototype = jQuery.prototype. But jQuery.fn.init is a different function than jQuery.
Applied to your example:
var jQ = function (arg){
return new jQ.prototype.init(arg);
};
jQ.prototype = {
init: function(arg) {
this.own = arg;
},
// ...
};
jQ.prototype.init.prototype = jQ.prototype;
I can't seem to find an example of what I'm trying to achieve, although I'm sure it has been done many times before...
I want to create an object which will have a set of properties and member functions but that I can also call directly. In the same way the jQuery object allows you to call $("selector") or $.method(...)
Here's a slimmed down version of what I'm trying to achieve :
var foobar = function(param) {
return "FOO : " + this.lookup(param);
}
foobar.vals = {
1: "one",
2: "two"
};
foobar.lookup = function (param) {
return "BAR : " + this.vals[param];
}
foobar.lookup("1")
// returns "BAR : one"
foobar("1")
// returns error since 'this' points to global scope
// I'd want it to return "FOO : BAR : one"
I've also tried various approaches with function prototype but can't seem to find a method which gives me everything I want...
var foobar = function(param) {
return "FOO : " + foobar.lookup(param);
}
will return you what you want
To understand this, maybe you should take a look at the basics of JavaScript. What are functions how to instanciate an object and what are objects...
To get something like JQuery this is not very difficult, the JQuery main object is simply a function which also has "static" functions.
to declare a variable as function you do
var myFunc = function(){};
to use the variable and extend it with static stuff you simply assign it via
myFunc.staticFunc = function(){};
this doesn't mean that myFunc.staticFunc can be accessed with this in any instance of myFucn because you didn't add the function to the prototype...
To define a class like object which can be instanciated you also define it as function and then extend the prototype. Prototype is your class definition which is used to construct the object's instance:
myFunc = function(){
// ctor
this.lala = "blub";
} ;
myFunc.prototype.objectFunc = function() {
return this.lala;
}
now the object myFunc has a function objectFunc. I have to initialize it with new...
alert(new myFunc().objectFunc());
instances can access itself with this...
To do something like jquery you'll have to do some tricks. Your global variable must be a function which returns an instance of your "real" object, which can implement whatever...
Then you can call your variable as if it is a function, e.g. myFunc()...
Hope the following example makes it more clear how this works: (can be found on jsfiddle)
(function ($) {
var myRealObj = function (outId, printText) {
this.text = printText;
$("#" + outId).append("<li>" + this.text + "</li>");
};
myRealObj.prototype.objectFunc = function () {
return this.lala
};
var myFunc = function (out, txt) {
return new myRealObj(out, txt);
};
myFunc.someFunc = function () {
myFunc("out", "myFunc.someFunc got called");
};
myFunc.static = {};
myFunc.static.someFunc = function () {
myFunc("out", "myFunc.static.someFunc got called");
};
window.$$ = myFunc;
})($);
$$("out", "test obj function");
$$.someFunc();
$$.static.someFunc();
You could add:
foobar = foobar.bind(foobar);
to make the variable refer to a bound version of the function. Any call to the (updated) "foobar" would have this bound to the original function object. You'd also have to mirror the properties if you wanted to get at them directly, which is sort-of a mess.
In the jQuery implementation, there's a separate internal function that handles the basic routing of the master $() function.
Note also that the "global" $.whatever() functions don't really have much to do with the set of methods supported by jQuery instances (objects returned from the $() function). The $ object just serves as a namespace so that those global utilities don't pollute the global (window) namespace.
you declare var foobar = function(param) {... in the global scope so this will always be a window
I try to bind a function but I dont really know how its work
For example
q={};
q.e=function(){return 1;}
q.e.i=function(){alert(this);}
q.e().i(); //Nothing happend I excepted that it will alert 1
So how does it work?
Thank you.
A function does also inherit from Object in Javascript. Hence you can assign properties to a function object, which you're just doing by calling
q.e.i = function() {};
but thats it. If you want to call it, you need to the same semantics
q.e.i();
in your current snippet, you're trying to execute .i() on the return value of e(), which happens to be the number 1.
You should be getting an error when calling q.e().i(); q.e() == 1 so (1).i() is an error since the Number object doesn't have an i method.
Hard to help since the code doesn't make any sense. I can only say that what you expected doesn't make sense in my head :)
Here's some code that would do what you expect
var q = {};
q.e = function() { return 1; };
q.e.i = function() { alert(this); }
// Call q.e.i, specifying what to use as this
q.e.i.call(q.e());
The trick is that in JS, this changes depending on how you call the function.
function a() {
console.log(this);
}
var obj = {
method: a
};
// Outputs the window object, calling a function without a `.` passes
// The window object as `this`
a();
// Outputs the obj, when you say obj.method(), method is called with obj as `this`
obj.method();
// You can also force the this parameter (to the number 1 in this case)
// outputs 1
obj.method.call(1);
I have this fragment of code from a book I am reading. And want to understand what $({}) means and what is its use exactly.
I tried searching on several search engines and even on SO. $({}) wasn't a search-friendly term.
var Events = {
bind: function(){
if ( !this.o ) this.o = $({});
this.o.bind.apply(this.o, arguments);
},
trigger: function(){
if ( !this.o ) this.o = $({});
this.o.trigger.apply(this.o, arguments);
}
};
I did find a similar question about $([]) but I don't think it is quite the same thing.
You're just wrapping a basic javascript object as a jQuery one.
From jquery documentation :
Working With Plain Objects
At present, the only operations supported
on plain JavaScript objects wrapped in jQuery are:
.data(),.prop(),.bind(), .unbind(), .trigger() and .triggerHandler().
The use of .data() (or any method requiring .data()) on a plain object
will result in a new property on the object called
jQuery{randomNumber} (eg. jQuery123456789).
// define a plain object
var foo = {foo:'bar', hello:'world'};
// wrap this with jQuery
var $foo = $(foo);
// test accessing property values
var test1 = $foo.prop('foo'); // bar
// test setting property values
$foo.prop('foo', 'foobar');
var test2 = $foo.prop('foo'); // foobar
// test using .data() as summarized above
$foo.data('keyName', 'someValue'); console.log($foo); // will now contain a
// jQuery{randomNumber}
// property
// test binding an event name and triggering
$foo.bind('eventName', function (){
console.log('eventName was called');
});
$foo.trigger('eventName'); // logs 'eventName was called'
Should
.trigger('eventName') be used, it will search for an 'eventName'
property on the object and attempt to execute it after any attached
jQuery handlers are executed. It does not check whether the property
is a function or not. To avoid this behavior,
.triggerHandler('eventName') should be used instead.
$foo.triggerHandler('eventName'); // also logs 'eventName was called'
Here's a (not really useful) example :
​var a =$({});
a.data('b', 3);
console.log(a.data('b')); // this prints 3
If you keep your object created with $({}), you may use it as callee for data, bind, and so on. This is probably the minimal non DOM keepable jquery object you can make.
this really has more to do with javascript syntax than jQuery.
{} is for objects like so:
//makes an empty object
var myObject = {};
//makes an object containing 'foo' and 'bar' as 'firstItem' and 'secondItem'
var myObject = { firstItem : foo, secondItem : bar };
[] is for arrays like so:
//makes a blank array
var myArray = [];
//makes an array containing 'foo' and 'bar' at postions 0 and 1
var myArray = [foo, bar];
() is for functions (which jQuery generally is). This is abit more complicated because it can have multiple meanings.
//running an existing function
myFunction();
//running an anonymous function
(function(){
//doSomething }
)();
//running a function with an argument
myFunction(arg);
jQuery is generally just a function called $ instead of myFunction so...
//runs jQuery as a function on 'arg'
$(arg);
The argument you pass jQuery can be almost anything. If you pass it a string like '#myDiv' jQuery will use that argument as a selector to get an element from the html. If you pass it something else like an object or an array, it can still do some things with it like: http://api.jquery.com/jQuery/ as #dystroy said.
So $({}) is the same as $(myBlankObject), for example:
var myBlankObject = {};
$(myBlankObject);
//is the same as
$({});
and
var myObjectWithStuff = { firstItem : foo, secondItem : bar };
$(myObjectWithStuff);
//is the same as
$({ firstItem : foo, secondItem : bar });
$('selector') works. $({'selector'}) or $(['selector']) does not, because you are not passing jQuery a string, but another data type.
I have a question on 'call' in javascript.
var humanWithHand = function(){
this.raiseHand = function(){
alert("raise hand");
}
}
var humanWithFoot = function(){
this.raiseFoot = function(){
alert("raise foot");
}
}
var human = function(){
humanWithHand.call( this );
humanWithFoot.call( this );
}
var test = new human();
so..when I use 'call' as humanWithHand.call(this), what happens internally?
does humanWithHand variable copies (or points?) its properties and members to human variable's prototype?
Yehuda Katz has a good writeup of JavaScript's Function#call method. His writeup should answer your question, and many followup questions besides.
When you call a function directly, using the general syntax:
var foo = function() {
console.log("foo");
return this;
};
foo(); // evaluates to `window`
Then this inside the function call is whatever this is outside the function call. By default, in the browser, this outside any function calls is window. So inside the function call as above, this is also by default window.
When you call a function using the method-call syntax:
var bar = {
foo: function() {
console.log("foo");
return this;
}
};
bar.foo(); // evaluates to `bar`
Then this inside the function call is the object to the left of the rightmost period: in this case, bar.
We can simulate this situation using call.
When you set up a function outside an object and want to call it with this inside the function call set to an object, you can:
var foo = function() {
console.log("foo");
return this;
}
var bar = { };
foo.call(bar); // evaluates to `bar`
You can use this technique to pass arguments as well:
var foo = function(arg1, arg2) {
console.log("foo");
return arg1 + arg2;
}
var bar = { };
foo.call(bar, "abc", "xyz"); // evaluates to `"abcxyz"`
.call() sets the this value and then calls the function with the arguments you passed to .call(). You use .call() instead of just calling the function directly when you want to set the this value inside the called function rather than let it be set to whatever javascript would normally set it to.
.apply() is a sister function. It can also set the this value and it can take arguments in an array so it can be used when you are trying to pass a variable argument list from some other function call or when you're constructing an argument list programmatically which may have different numbers of arguments depending upon the situation.