讨论JavaScript 按anyonymous function的用法
funcion expression 和 function declaration的细微差别
===============================
Link: http://thoughtsonscripts.blogspot.com/2012/01/javascript-anonymous-functions.html
JavaScript can definitely look weird and convoluted, even in those code people say are just about "relatively simple concepts" and "are applied in practice quite often". For example, this littleJavaScript quiz. And cherry pick one example:
var foo = { bar: function() { return this.baz; }, baz: 1 }; (function(){ return typeof arguments[0](); })(foo.bar);
It sure looks weird and convoluted to me.
About half of the weird-ness about JavaScript has to do with anonymous function, the way it is created, called, passed with parameters, passed around. That said, anonymous function is definitely ubiquitous and indeed worthy of some true understanding.
Anonymous function by definition is simple. It is just a function without name (in contrast to a non-anonymous function that has a name).
Example of a non-anonymous function:
function sayHello(){ alert("hi"); }
Example of a anonymous function:
var sayHello = function(){ alert("hi"); };
What's the difference between the two
sayHellos
? Logically they are the same. However, the second one is an expression, an anonymous function assigned to a variable
sayHello
; The first one is a function declaration, while the second one a function expression. This causes the difference how they can be accessed.
Example of different accessibility between anonymous function and non-anonymous function:
// anonymous function assigned to a variable cannot be called before the variable is initialized fnAnonymous(); // undefined var fnAnonymous = function(){ alert("hi"); }; fnAnonymous(); //hi // a named function can be accessed anywhere as long as it is within the same scope that the function is created fnNamed(); // hi function fnNamed(){ alert("hi"); }; fnNamed(); //hi
So even the above
fnAnonymous()
are
fnNamed()
are essentially the same, yet one (
fnNamed
) is created through function declaration, the other through function expression. The former (named function) is created in the scope before execution and can be assessed throughout in the same scope, while the later is created until the expression is evaluated and cannot be assessed before the line of evaluation.
Anonymous functions are created all the time, accidentally or not. They exist in different shapes and forms.
All the following involves anonymous functions:
// function expression var sayHello = function (){ alert("hi"); }; // in an object var Person = { sayHello: function(){ alert("hi"); } }; // event handler $("p").click = function(){ alert("hello"); }; // ajax callback from http://api.jquery.com/jQuery.ajax/ $.ajax({ url: "test.html", context: document.body, success: function(){ $(this).addClass("done"); } }); //Self-evoking anonymous functions ((function () { alert("hi"); })());
What are anonymous functions for? Benefits?
Simply, anonymous functions are used for the reasons of: a) code brevity. It often makes sense to use anonymous functions calls in callbacks and event handlers; b) scope management. Anonymous functions can be used to create temporary/private scope; c) Anonymous function are often handy in closures and recursions.
In JavaScript, scope could be tricky but it is fundamental to JavaScript understanding. And anonymous functions are often used to create a temporary / private scope.
A commonly cited example is jQuery.
(function( window, undefined ) { var jQuery = (function() { }); // Expose jQuery to the global object window.jQuery = window.$ = jQuery; // })(window);
The above ensures the function is called immediately; it also ensures every variable declared in the anonymous function is a private variable, therefore won't spill into and pollute the global scope, which is extremely important from a library's perspective; it also ensures that the scope chain is destroyed after the function finishes execution.
Recursions
Recursions are functions that call themselves, they are often used to solve problems such as factorials, the tower of hanoi, golden ratio (See wiki Recursion. Or, fibonacci numbers.
function fibonacci(n) { if (n < 2) return n; return fibonacci(n - 1) + fibonacci(n - 2); } alert(fibonacci(6)); //8
It works fine. But it can/should be improved with two things:
arguments.callee
and function memorization. As the following:
function f(n) { if (n < 2) return n; if (f.answers[n] != null) return f.answers[n]; f.answers[n] = arguments.callee(n - 1) + arguments.callee(n - 2); return f.answers[n]; } f.answers ={}; var fibo = f; alert(fibo(10)); //55 alert(fibo(11)); //89
So, first,
arguments.callee
. All functions have a pointer
arguments.callee
to itself. Using
arguments.callee
instead of the function names ensures that the function can always be accessed, even when the function is assigned to a variable; second, store the computed value in memory. Because all recursions involves doing the same calculation over and over again, we can just save some extra work and repetitions by storing the known/already computed answers.
Closures
Functions returned from another function are called closures. Closures and anonymous functions often goes hand in hand.
$('#foo').click( function() { alert('User clicked on "foo."'); });
Closures can often get into trouble with loops, and one sure way to get out of the loop is to use anonymous function to create a temporary scope.
So a loop like this is problematic.
for (var i = 1; i <= 10; i++) { $('#Div' + i).click(function () { alert('#Div' + i + " is kicked"); return false; }); }
Yet if you rewrite it a bit, it will work!
for (var i = 1; i <= 10; i++) { (function(v){ $('#Div' + v).click(function () { alert('Div' + v + " is kicked"); return false; }) })(i); }
Read more about closures at JavaScript closures
Back to the weird anonymous function
Now let's go back to the weird code that sits squarely in the quiz we mentioned in the beginning.
var foo = { bar: function() { return this.baz; }, baz: 1 }; (function(){ return typeof arguments[0](); })(foo.bar);
What would be the correct answer?
a) "undefined"
b) "object"
c) "number"
d) "function"
The answer is a) "undefined". I did not get this right until I ran the code. I cheated.
Brief explanation (found in the comments section):
"It’s important to understand that this is not a closure variable. Instead, it is determined at function-run-time, by the entity which it ‘belongs to’ at the time — and if there is no such object, then the object is window. So if you call foo.bar(), then this will point at foo. But when you call arguments[0](), it points at arguments instead. Since arguments.baz is undefined, you get this particular behaviour."
hmm. Takes some chewing.
A hasty conclusion
Well, there is still so much more about JavaScript anonymous function. And it could be a pain. If it is, hopefully this would alleviate your pain a bit.
So long!
相关推荐
Chapter 7: Anonymous Functions 183 Chapter 8: The Browser Object Model .201 Chapter 9: Client Detection 229 Chapter 10: The Document Object Model 261 Chapter 11: DOM Levels 2 and 3 .317 Chapter 12: ...
The compiler supports Object Pascal language based on the Delphi 7 standard and extends it with generic types, operator overloading, anonymous functions and closures, lambda-expressions. Syntax of ...
Logitall “ logitall全部记录下来!” logitall是一个“哑跟踪”调试工具,可在运行每行代码之前修改JavaScript文件中的所有代码,以... --named-functions-only only log non-anonymous functions and methods --r
The compiler supports Object Pascal language based on the Delphi 7 standard and extends it with generic types, operator overloading, anonymous functions and closures, lambda-expressions. Syntax of ...
The compiler supports Object Pascal language based on the Delphi 7 standard and extends it with generic types, operator overloading, anonymous functions and closures, lambda-expressions. Syntax of ...
Welcome to Express in Action! This book aims to teach you everything about Express.js, the web framework that makes the powerful Node.js easy to...things like anonymous functions, closures, and callbacks
Anonymous functions 79 Adding a div on the fly 79 Create a listener 80 Fetching data from another page 81 Creating our plugin 83 Creating index.php and activating the plugin 84 Creating our ...
JavaScript高级功能:基本功能回顾学习目标使用函数声明定义函数定义hoisting 定义function expression 定义anonymous function 使用函数表达式定义函数定义一个IIFE: Instantly-Invoked Function Expression 定义...
Anonymous Types 445 Extension Methods 449 Lambda Expressions 455 Summary 466 Exercises 467 Part II: Windows Programming 468 Chapter 15: Basic Windows Programming 470 Controls 471 ...
For this purpose, our system is designed to perfect some correlative functions, such as publish articles for the registration users, publish anonymous comments for the visitors, and complete the ...
// Putting a name on unnamed functions that initialize vars is easy var foo = function ( ) { } ; // becomes var foo = function anon$foo() {}; // Initializing fields is also easy { bar : function ( )...
functions. ; Possible Values: ; On = Enabled and buffer is unlimited. (Use with caution) ; Off = Disabled ; Integer = Enables the buffer and sets its maximum size in bytes. ; Note: This directive is ...
RnFireChat RnFireChat是第5个会话构建,用于显示Firebase用于构建聊天应用程序的实现; 聊天室和p2p以及用于推送通知的无服务器功能。 在这个master分支中,我们将使用分支中的构建布局,在该分支中,我们将使用...