`

JavaScript: Anonymous functions

阅读更多

讨论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!

分享到:
评论

相关推荐

    javascript加密器,需要.netframework2.0支持

    5. **自执行匿名函数(Self-executing anonymous functions)**: 通过立即执行的函数表达式,将代码包裹起来,隐藏其内部结构,限制外部访问。 尽管JavaScript加密可以提高代码的保密性,但并不能完全阻止有经验的...

    JavaScript.教程

    匿名函数 (Anonymous Functions) 匿名函数是没有名字的函数,通常作为参数传递给其他函数或立即执行。例如: ```javascript (function() { console.log("Hello World"); })(); ``` #### 2. 回调函数 (Callback ...

    javascript高级教程

    console.log("Anonymous function"); })(); ``` - **回调函数**: 函数作为另一个函数的参数传递,通常用于异步操作。 ```javascript function process(data, callback) { // 处理数据 callback(result); } ...

    Kotlin - Kotlin Language Documentation 2.0.0

    - **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") = ...

    PaxCompiler.v.4.2-10.3RIO

    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是一个命令行实用程序,它将console.log()添加到程序中的每一行代码

    Logitall “ logitall全部记录下来!” logitall是一个“哑跟踪”调试工具,可在运行每行代码之前修改JavaScript文件中的所有代码,以... --named-functions-only only log non-anonymous functions and methods --r

    paxCompiler 4.1 Full Sources

    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 ...

    paxCompiler v4.1 Full source

    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 ...

    jdk1.8-windows版64位

    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 ...

    js 二阶段诸葛韩寒的啊大苏打

    - 匿名函数:`var anonymous = function() { /* code */ };` - 立即执行函数(IIFE):`(function() { /* code */ })();` 3.0 数组、字符串和常用对象及方法 - 数组:使用方括号`[]`声明,支持索引访问和多种方法,...

    js-advanced-functions-basic-functions-review-lab-v-000

    JavaScript高级功能:基本功能回顾学习目标使用函数声明定义函数定义hoisting 定义function expression 定义anonymous function 使用函数表达式定义函数定义一个IIFE: Instantly-Invoked Function Expression 定义...

    jdk1.8_win64.rar

    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 ...

    Beginning Microsoft Visual CSharp 2008 Wiley Publishing(english)

    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 ...

    jdk1.8_win32.rar

    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 ...

    Laravel开发-laravel-bootstrap

    @import 'node_modules/bootstrap/scss/functions'; @import 'node_modules/bootstrap/scss/variables'; @import 'node_modules/bootstrap/scss/mixins'; // 自定义变量 $primary-color: #ff0000; // 自定义样式 ...

    基于JSP的博客系统论文+源码+数据库

    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 ...

    php解析umd脚本

    // Exposed functions or variables }; })); ``` 在PHP中处理UMD脚本,首先需要理解UMD的结构。由于UMD是文本格式,我们可以通过`file_get_contents()`函数读取文件内容,然后用`explode()`、`preg_match()`等...

Global site tag (gtag.js) - Google Analytics