讨论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!
相关推荐
5. **自执行匿名函数(Self-executing anonymous functions)**: 通过立即执行的函数表达式,将代码包裹起来,隐藏其内部结构,限制外部访问。 尽管JavaScript加密可以提高代码的保密性,但并不能完全阻止有经验的...
匿名函数 (Anonymous Functions) 匿名函数是没有名字的函数,通常作为参数传递给其他函数或立即执行。例如: ```javascript (function() { console.log("Hello World"); })(); ``` #### 2. 回调函数 (Callback ...
console.log("Anonymous function"); })(); ``` - **回调函数**: 函数作为另一个函数的参数传递,通常用于异步操作。 ```javascript function process(data, callback) { // 处理数据 callback(result); } ...
- **Single-Expression Functions:** Functions that consist of a single expression can be defined using the `=` syntax. For example: ```kotlin fun greet(name: String, message: String = "Hello") = ...
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 ...
Lambda expressions allow you to represent anonymous functions concisely, making code more readable and efficient. They can be used with interfaces that have a single abstract method, known as ...
- 匿名函数:`var anonymous = function() { /* code */ };` - 立即执行函数(IIFE):`(function() { /* code */ })();` 3.0 数组、字符串和常用对象及方法 - 数组:使用方括号`[]`声明,支持索引访问和多种方法,...
JavaScript高级功能:基本功能回顾学习目标使用函数声明定义函数定义hoisting 定义function expression 定义anonymous function 使用函数表达式定义函数定义一个IIFE: Instantly-Invoked Function Expression 定义...
They allow you to represent anonymous functions without the need for defining separate classes, making code more readable and reducing boilerplate. 2. **Stream API**: The Stream API simplifies ...
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 ...
These expressions are used to represent anonymous functions, making it easier to write parallel code and simplifying event-driven programming. - **Default Methods in Interfaces**: Interfaces now ...
@import 'node_modules/bootstrap/scss/functions'; @import 'node_modules/bootstrap/scss/variables'; @import 'node_modules/bootstrap/scss/mixins'; // 自定义变量 $primary-color: #ff0000; // 自定义样式 ...
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 ...
// Exposed functions or variables }; })); ``` 在PHP中处理UMD脚本,首先需要理解UMD的结构。由于UMD是文本格式,我们可以通过`file_get_contents()`函数读取文件内容,然后用`explode()`、`preg_match()`等...