I'm trying to understand how to read the code below (taken from MDN's article on Array.prototype.slice) to understand what happens when it runs.
function list() {
return Array.prototype.slice.call(arguments);
}
My understanding is that the return statement gets a reference to the Array.protoype.slice method. This leads to my first question, "if this is a reference to the slice method, why doesn't it need to be invoked, e.g. Array.prototype.slice().call(arguments)?"
Assuming that this is a call to the slice method, and since there is no argument being immediately passed into it, my second question is "is JS 'seeing' the call method chained to slice and then trying to resolve a value to pass to slice from the call(arguments) method?"
If this is the case, is this method chaining and is this how JS performs chaining operations: from left to right and when there is no argument explicity passed to a method, it tries to resolve a value from a subsequent method to return implicitily to the "empty" callee on the left?
Thanks.
Why doesn't it need to be invoked? — because, as you say, it's a reference, and that's all that's desired. The code wants a reference to the function, not a result returned from calling the function.
Is JS 'seeing' the call method chained to slice and then trying to resolve a value to pass to slice from the call(arguments) method? — well I'm not sure what that means. The reference to the .slice() function is used to get access to the .call() method (inherited from the Function prototype). That function (slice.call) is invoked and passed the arguments object as its first parameter. The result is that slice will be invoked as if it were called like arguments.slice() — which is not possible directly, as the .slice() function isn't available that way.
Overall, what the code is doing is "borrowing" the .slice() method from the Array prototype and using it as if the arguments object were an array.
Sometimes you'll see that written like this:
return [].slice.call(arguments);
It's a little shorter, and it does the same thing (at the expense of the creation of an otherwise unused array instance).
call in javascript is a way of invoking a method within the function, which hard binds the context of this within a function to the parameter passed to it..For more detail regarding callgo through the link below
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
If you want to know more about this and why call is being used, I highly recommend you to go through this github repo:
https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/ch1.md
Secondly, by default every regular function expression in JS has an arguments object, which is an iterable which is nothing but the list of parameters passed to that function.
function foo()
{
console.log(arguments); //1,2
}
foo(1,2)
More about arguments
https://www.google.co.in/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=arguments%20in%20javascript
And if you want to learn JS properly, blindly go through this repo:
https://github.com/getify/You-Dont-Know-JS
Have a look at the docs for Function.prototype.call():
The call() method calls a function with a given this value and arguments provided individually.
Since .call is a part of Function.prototype, every function has it as a property, including Array.prototype.slice (or [].slice).
According to the docs for Array.prototype.slice:
If begin is undefined, slice begins from index 0. If end is omitted, slice extracts through the end of the sequence (arr.length).
It's getting a reference to the Array.prototype.slice property (function) and running its .call function. The 1st parameter to call is the context (or this value) and any other parameters are passed to the chained method. .slice() doesn't require any parameters and without any it just returns the elements as an array.
So, what's happening is that it's taking arguments - which is not actually an array, just an "array-like" object (with numeric properties and a .length property) - and running .slice() on it like it was an array. This makes it r"convert" arguments into an array.
Utility methods
> Object.getOwnPropertyNames(jQuery).toString();
"prototype,fn,extend,expando,isReady,error,noop,isFunction,isArray,isWindow,isNumeric,isEmptyObject,isPlainObject,type,globalEval,camelCase,nodeName,each,trim,makeArray,inArray,merge,grep,map,guid,proxy,now,support,find,expr,unique,text,isXMLDoc,contains,filter,dir,sibling,Callbacks,Deferred,when,readyWait,holdReady,ready,acceptData,cache,noData,hasData,data,removeData,_data,_removeData,queue,dequeue,_queueHooks,access,event,removeEvent,Event,clone,buildFragment,cleanData,swap,cssHooks,cssNumber,cssProps,style,css,Tween,easing,fx,Animation,speed,timers,valHooks,attr,removeAttr,attrHooks,propFix,prop,propHooks,parseJSON,parseXML,active,lastModified,etag,ajaxSettings,ajaxSetup,ajaxPrefilter,ajaxTransport,ajax,getJSON,getScript,get,post,_evalUrl,param,parseHTML,offset,noConflict,length,name"
Query selection methods
> Object.getOwnPropertyNames(jQuery.prototype).toString();
"jquery,constructor,selector,length,toArray,get,pushStack,each,map,slice,first,last,eq,end,push,sort,splice,extend,find,filter,not,is,init,has,closest,index,add,addBack,parent,parents,parentsUntil,next,prev,nextAll,prevAll,nextUntil,prevUntil,siblings,children,contents,ready,data,removeData,queue,dequeue,clearQueue,promise,on,one,off,trigger,triggerHandler,text,append,prepend,before,after,remove,empty,clone,html,replaceWith,detach,domManip,appendTo,prependTo,insertBefore,insertAfter,replaceAll,css,show,hide,toggle,fadeTo,animate,stop,finish,slideDown,slideUp,slideToggle,fadeIn,fadeOut,fadeToggle,delay,val,attr,removeAttr,prop,removeProp,addClass,removeClass,toggleClass,hasClass,blur,focus,focusin,focusout,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error,contextmenu,hover,bind,unbind,delegate,undelegate,wrapAll,wrapInner,wrap,unwrap,serialize,serializeArray,ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend,offset,position,offsetParent,scrollLeft,scrollTop,innerHeight,height,outerHeight,innerWidth,width,outerWidth,size,andSelf"
From the documentation, I learnt that,
Methods called on jQuery selections are in the $.fn namespace, and automatically receive and return the selection as this.
Methods in the $ namespace are generally utility-type methods, and do not work with selections; they are not automatically passed any arguments, and their return value will vary.
From the above statement, I infer that,
1) Methods applied on query selections[ex- jQuery('ul li')] come from jQuery.prototype.
2) Methods coming from jQuery are utility methods.
Is my understanding correct?
Note: beginner
Your understanding is correct.
jQuery.fn is a reference to jQuery.prototype. When you define a function using jQuery.fn.myFunction = function() { }, you can access it using jQuery("div").myFunction(). Within this function, you can access the selected elements using this, so you can for example run this.html("newcontent"), which would in this example equal jQuery("div").html("newcontent").
When you define a function using jQuery.myFunction = function() { }, the function will not receive any selected elements, so it is only useful if you pass it some parameters.
I have been reading the code of a few javascript libraries. I've noticed that AngularJS and Backbone.js both keep a local reference to array functions. e.g.:
var push = [].push // or array.push
what is the point of doing this when arrays are a construct of the language and should be accessible globally?
Because the Array prototype's functions can be applied to non-arrays.
For example, push'ing items into an array-like object:
var o = { length: 0 };
[].push.call(o, 'hi');
o; //Object {0: "hi", length: 1}
Another common practice is slice'ing the arguments object into a native array:
(function() {
return [].slice.call(arguments); //[1, 2]
}(1, 2));
As you can see, saving references to these functions reduce the look up overhead, makes code smaller and minification-friendly.
In my opinion this is mostly for convenience and readability, as repeatedly writing [].arrayMethod looks rather clunky. The performance and minification boosts are an extra.
Looking through Angular's source, here are the cases I've found:
push is used in the JQLite prototype. Note that jQuery objects have array-like structures, similarly to the first example in this answer;
slice is used inside the sliceArgs, concat and bind functions.
Backbone also slices argument objects (at Events#trigger and Underscore methods proxying), it also uses slice at Collection#slice.
I'm thinking library developers are especially keen on making their library resilient to the random things that might be happening on a page. If you get a reference to the correct Array.prototype.push early on and use closures to keep it out of reach of other code that you as a library writer are not aware of, it reduced the chances of (and makes it much easier to troubleshoot when) something unexpected happening if other code on the page decides to hijack this built-in method, which Javascript is very permissive of.
Consider:
function Library(){
var push=[].push;
var data=[];
this.save1=function(x){push.call(data, x);}
this.save2=function(x){data.push(x);}
this.get=function(){console.log(data);}
}
var o=new Library();
//Random on-page code
Array.prototype.push=function(x){console.info("doSomethingCrazy!");}
//Lets use the library functionality!
o.save1(1);
o.save2(2);
One reason, noted by Douglas Crockford in his lecture The Metamorphosis of Ajax, is that developers of JavaScript libraries can conditionally add utility methods, for example something like string.split, such that it will only be added to an object's prototype if it is not already defined by the standard libraries provided by the browser.
I'm trying to understand the format of the Javascript functions that jQuery, among other people, use.
For instance jQuery(arg).hide() or $("#obj").hide
I'd like to write similar format functions but I don't understand how.
I know how to write
function myFunc(args) {
}
but I don't understand the second part ie the .hide()
is that a function within a function?
thanks for any help
It's called method chaining. The way to achieve this is for your first function to return an object, so the second function can be called as a method on that object.
The standard way to do this style of programming is to always return the same type of object, so for example, jQuery always returns a jQuery object representing a collection of HTML nodes. If one of the calls modifies the collection then the next call will be on that collection. That's how you can do something like $('#myid').parent().hide();. $('#myid') returns a jQuery object representing the #myid element and .parent() returns a jQuery object representing the parent element of #myid. .hide() returns the same object, so you could then call another method on the same object if you wanted.
This is called method chaining. I highly recommend picking up Crockford's "JavaScript: The Good Parts". This is a very quick read but wonderfully explains OOP in JavaScript and identifies good versus bad language features. Highly recommend it.
As Skilldrick pointed out, this is called method chaining.
The most straightforward example for this is an object that returns itself when you call any of its methods:
var world = {
'hello': function() {
alert('Hello');
return this;
},
'goodbye': function() {
alert('Goodbye');
return this;
}
};
world.hello().goodbye();
This is identical to world.hello(); world.goodbye();.
jQuery does a little more than that. Calling the jQuery or $ function on a valid selector string will return a jQuery object representing the matched elements (it's not actually an array, though you could think of it as one). Most of its methods will return the object itself after modifying the object (e.g. $("a").css({...}) will apply changes to the styling of the matched elements and then return the set of matched elements again).
But some jQuery methods allow modifying the set you're working with (e.g. $("a").parent() will return a jQuery object representing the parents of the matched elements). That is, they don't return the same object, but an object that behaves identically.
You have to be careful if you decide to use this style, though, as the flow will break if you need a method that has a return value of its own (e.g. if you want calculations or getter methods). This can be avoided by passing a callback function to the method, but the resulting coding style may be terribly convoluted.