|
網誌存檔
熱門網志
|
|
Functional JavascriptFiled: Mon, Apr 02 2007 under Programming|| Tags: reference functions javascript howto reference Lisp? Scheme? Erlang, Haskell? Forget about them! The most widely deployed functional programming language is Javascript. Borrowing a trick or two from the transformers, Javascript masquerades as a procedural language until you`re ready to take it to the next level. Procedural FunctionsIn the beginning there was the function… function hello(who) { Nearly every programming language has a construct similar to this. Every programmer in the world is comfortable with this syntax. Functions As VariablesIt may be a little unfamiliar in syntax but most programmers should be comfortable with a function that`s defined like a variable. var hello = function (who) { There`s no big difference here, just add a Take a look at that definition again. This is more than just visual It will have the same scope and it can be passed to other functions just like any other variable. Passing Functions To FunctionsIf we declare var say = function(what) { So in Javascript a function can be passed just like an array or an object or any other variable. Or put another way, anything that can hold a value in javascript can hold a function. There are two ways to use a function as an argument. You can pass a pointer to the function itself, or you can execute the function in the call and pass the return value of the function. The example above passed a pointer of the If you`ve ever made an event in Javascript you`ve probably already used the function doSomething() { This example gives the function function pushedMyButton() { Now when the onclick event is set up, doSomething is executed because we appended parenthesis at the end. The parenthesis are an empty set -- we`re not passing anything -- but that`s ok, they tell javascript that we want to execute the function not pass a pointer to it. If Just to recap; if you don`t follow a function name with argument parenthesis then you`re passing the function as a pointer. If you follow up a function name with argument parenthesis, even if they`re just an empty set -- (), Javascript will execute the function and pass along the return value of the function. Keep that difference in mind, we`ll be coming back to it a little later. var test = function () { Lambda, Lambda, LambdaIf you`ve mastered the concept of passing functions as arguments to other functions then congratulations! You now understand lambda which basically just means using a function as an argument in a call to another function. Lambda is a pretty big buzzword in functional programming and it gets thrown around a lot. Worse, it gets thrown around like everyone already knows that lambda is using a function in an argument in a call to another function. So if you see something like "Here we`ll use a lambda expression" it just means they`re passing a function as an argument. Visually, in psuedo-code, Lambda is represented by the As an aside, it`s probably pure coincidence that Lambda Lambda Lambda was the fraternity in Revenge of the Nerds. Anonymous FunctionsChances are, if you`ve ever written an Ajax routine or an Event handler in Javascript you are familiar with an anonymous function. For instance… document.onmousedown = function() { alert("You pressed the mouse button"); } This sets up an event handler whenever the mouse is pressed. When the mouse button is pressed, the handler calls the anonymous function which simply throws up an alert box. This function is anonymous because we didn`t declare a name for the function, we can`t call it later unless we somehow go through onmousedown. Which leads us to another concept of functional programming. If a function doesn`t have a name, and it`s just another value in the machine, then functions in Javascript are much closer to data than what we would consider traditional functions and objects. It`s data that does stuff to be sure, but in every place that matters, learning to look at the function as a piece of active data will really help you out when it comes to figuring out just how to apply this technology. Self-Invoking FunctionsConsider for a moment the following code… var x = (function () {return(5+6)})(); This is an anonymous, self-invoking function and it`s really quite powerful, although it`s hard to see that power in the little example. What we did here was wrap a function in parenthesis and then add in the argument parenthesis. When javascript comes across this line it will execute the function and put the return value in x. That`s it. The function existed only long enough to generate A more common real-world example of this is the following bookmarklette code which attaches an external Javascript to the current page. ( function () { This code, when executed, creates a new <A HREF=`javascript:(function(){var s=document.createElement("script"); s.src="http://mydomain.com/script.js"; document.body.appendChild(s);})();`>My First Bookmarklete App</A> You can learn more about bookmarklettes in the article: Bookmarklets -- The Evil Lurking In Your Browser. You can also use self-invoking functions lambda (buzzword!) as a sort of shortcut when you need to do some light processing of data before you pass it on to another function. Observe… function doAlert(msg) { In this example we have a traditional doAlert(msg) function, but it`s invoked with an anonymous, self-invoking function as its msg argument. msg will be the returned value of the anonymous function. To further illustrate how anonymous and self-invoking functions work, this example uses two arguments in the self-invoking function. It accepts animal1 and animal2 as arguments and it gets those values from the trailing parenthesis which pass `cat` and `dog` respectively. And of course `cat` and `dog` could be variables, and doAlert could be in a loop zipping through an array of data. Something like this… function doDisplay(msg) { Here we actually have a loop set up. For ten times, it will call doDisplay and its self-invoking function will set up a string to pass to doDisplay. The trailing parenthesis pass the arguments to the anonymous-function, and these values will be used to set up the string. Well that pretty much covers anonymous, self-invoking functions, but as you might have suspected you can also do named, self-invoking functions as well! Here`s a modification of the example above where the anonymous function has been changed to be a regular function named buildString. function doDisplay(msg) { And of course this is just a variation on the more traditional function call… function doDisplay(msg) { Which will work equally well. Understanding Function PointersWhen you create a function, that function occupies a block of memory. Internally, the only reference it has is its location in Javascript`s heap. When you pass a pointer to the function you`re passing the pointer to this memory location and NOT the function`s name. This is best illustrated in code… var originalFunction = function () {
Understanding Function ScopeBecause Javascript functions are treated like ordinary variables, they have the same scope and rules as ordinary variables -- which, in javascript, can be a little quirky. Functions defined at the <script> level are global, accessible to every function, object, array, and sub-function regardless of their location in the code. Variables in Javascript have function scope not block scope which means that -- with one caveat -- variables defined inside a function are private to that function and its sub-functions or children. var globalFunction = function () { // global, can be accessed anywhere. The caveat? The caveat is if you declare a new variable without the var keyword inside a function it becomes global in scope. It`s a quirk of the language that catches many people unawares. var globalFunction = function () { // global, can be accessed anywhere. Functions As ObjectsAll functions in Javascript are objects. This is mostly transparent until you deliberately set out to create object-oriented code. An Array, in Javascript, is also an object. At its top level an Array is an Array… var myArray = []; Underneath myArray is its object, which has properties and methods common to all Arrays and which you can extend upon. var myArray = []; Here we load up both the array and the properties of the Array object. When we loop through myArray we`re only going to get back [1][2][3] (1,2,3), the properties (`one`,`two`,`three`) aren`t a part of the real array they`re properties of its object. But check out the loop statement. We used the .length property to find out how many items were in the array. So the Array, in Javascript, exists on two levels. At the top we have the Array itself and below that is the object for that Array which we can also use to store data in its properties and create any methods we want in addition to drawing on common methods and properties all Arrays share (like .length, .sort, .concat, etc). Functions, in Javascript, are like Arrays in that at the top level you have the function itself. It does what you define it to do. But underneath that is the function`s object and that object has common properties and methods and those properties and methods can be extended on by you, as needed. Function Objects and MethodsEvery function has the following properties…
Every function has the following methods…
Understanding Function ArgumentsThe argument list in your function declaration can be considered a recommendation. If you have the following… var myFunc = function(a,b,c) { } You can still call the function the following ways… myFunc(1); If myFunc(1) is called then b and c will be of type var myFunc = function(a,b,c) { As you can see, undefined is a false condition so you can use boolean operators to detect if an argument wasn`t set and correct it. The safest way to correct for an unsent argument is to look for The function .length property and the arguments.length property allow you to check for the expected number of arguments and the number of arguments actually passed. For instance… var myFunc = function(a,b,c) { As you can see, the function expected 3 arguments but got only 1! Mastering the Arguments ArrayIn our example above a,b, and c represented variables we used to capture the first three arguments. If there weren`t enough arguments the variables were set to var myFunc = function() { After this article was published Matthew Eernisse (Author of Build Your Own Ajax Web Applications) noted that the arguments property isn`t the same as user-defined arrays. While you access the elements the same and .length is the same, the arguments array doesn`t have all the methods (sort, splice, slice, etc) that a user-defined array contains. If you`d like to be able to manipulate the arguments array with the same tools you use to manipulate a normal array, Mr. Earnisse provided a very elegant solution. var args = Array.prototype.slice.apply(arguments); With this code args becomes a proper array copy of arguments. Howto Pass Arguments To Another FunctionEvery now and again, someone asks how to pass the arguments to another function as arguments instead of an array. For instance… var otherFunc=function() { Here we pass 10 arguments to myFunc and myFunc tries to pass them to otherFunc but instead we pass it the arguments array and not an arguments list. We can work around this with a function method called apply which will apply the arguments array as an arguments list in the new function. var otherFunc = function() { Howto use recursion on Anonymous FunctionsLets say we have an anonymous factorial function and we want to do it recursively. How do we call a function without a name? Well in Javascript the arguments.callee property contains a pointer to the currently executing function which means an anonymous function can, indeed, call itself. alert((function(n){ if(n <= 1){return 1;}else{return n*arguments.callee(n-1);}})(10)); ConclusionThere`s a lot more to functions in regards to object oriented programming and the Javascript Function object, but that is subject matter for another, future, article. For now, however, I hope this article has helped you grasp the power and flexibility Javascript functions afford you in expressing your programming goals. |
-------------------------------------------------
| 上一篇:Mastering Javascript Arrays | 下一篇:Javascript Dates-The Complete Reference |

