详细研究过Javascript代码库(如Jquery、YUI)的人,一定会看到过很多如下形式的函数: (function(){...}()) 或 (function(){})()
对于很多初学者来说,遇到它们经常会产生一系列问号:这是编程吗,用它做什么,怎么我没在其他语言里见过呢?
接下来我就详细地解释一下:
它可以解释成为“匿名函数自调用”,也就是说,定义一个匿名函数,然后马上调用它(因为它是匿名的,如果不立即调用就获取不到该函数的引用了)。通常它被应用在一些大型的JS框架中(如上面所说的),因为这个匿名函数的函数体相当于提供一个匿名的名字空间,这样就不会再与用户自定义的JS函数、变量、对象发生冲突了。尽管JS没有显示地提供命名空间的定义和使用机制,但这种匿名方式却不失为是一种很好的解决命名空间问题的方法。
所以说,(function(){代码})()就等于执行了一个函数,只不过它是匿名的而已。如果在这个匿名函数内部想再次调用这个函数,就需要调用constructor属性了(这是Object中定义的,JS的继承机制如同Java一样保证了了所有对象都继承Object类)。
明白了它是什么了,下面我们就要学习该怎样使用它了,以下这些问题是我们会经常遇到的,不如提前做好理论只是准备以备后期能顺利地实现开发。请看下面问题:
1、下列哪些正确?(B、C)
A.function(){
alert("Here!");
}();
B.(function(){
alert("Here!");
})();
C.(function(){
alert("Here!");
}());
2、下列哪个结果是正确的?(A、B、C、D)
A.(function(a1,a2){
alert("Here!"+(a1+a2));
})(1,2);
B.(function(a1,a2){
alert("Here!" +(a1+a2));
}(1,2));
C.void function(a1,a2){
alert("Here!" +(a1+a2));
}(1,2);
D.var f = function(a1,a2){
alert("Here!" +(a1+a2));
}(1,2);
注:A 、B、C与D四种格式都正确,前两者属于同种情况的不同写法,后两种是将函数对象的返回值赋给其他变量,C是忽略函数返回值,而D正相反!
具体举个例子:
function test(){
return (function(p1,p2){
return p1+p2;
})(1,2);
};
(function(){
alert(test());
}());
下面我们就深入研究一下这种匿名函数:
1、
①
function Foo() {
var a = 123;
this.a = 456;
(function() {
alert(a); // 123
alert(this.a); // undefined
})();
};
var f = new Foo();
②
function Foo() {
var a = 123;
this.a = 456;
(function(_this) {
alert(a); // 123
alert(_this.a); // 456
})(this);
};
var f = new Foo();
以上两个对比,说明:
(1)匿名函数可以直接访问到外层署名函数(Foo)中的变量(使用关键字var定义的),但不能访问外层署名函数的属性(使用关键字this定义的);
(2)匿名函数中的this指向的是匿名函数对象的地址,它与外层署名函数(Foo)对象的this指向的地址不同;
(3)匿名函数若要访问外层署名函数(Foo)中的属性,可以通过参数传递的方式实现。
2、
①
function Foo() {
var a = 123;
this.a = 456;
(function(b) {
alert(a); // 123
alert(b); // 456
})(this.a);
};
var f = new Foo();
②
(function() {
var a = 123;
this.a = 456;
(function() {
alert(a); // 123
alert(this.a); // 456
})();
})();
以上两个对比,说明:
(1) 匿名函数既可以直接访问外层匿名函数中的变量,又直接可以访问外层匿名函数中的属性,而匿名函数却不可以直接访问外层已命名函数中的属性;
(2)以上两种方式可以实现相同的功能。
3、
①
(function() {
var a = 123;
this.a = 456;
(function() {
alert(a); // 123
alert(this.a); // 456
this.b = 789;
})();
(function() {
alert(this.b); // 789
})();
})();
(function() {
alert(this.a); // 456
alert(this.b); // 789
})();
②
function Foo() {
var a = 123;
this.a = 456;
(function() {
alert(a); // 123
alert(this.a); // undefined
this.b = 789;
})();
(function() {
alert(this.b); // 789
})();
};
var f = new Foo();
(function() {
alert(this.a); // undefined
alert(this.b); // 789
})();
以上两个对比,说明:
(1)匿名函数(即用两个小括号括起来的部分)位于一个执行上下文,不论这些代码放在哪个位置上。
4、
①
function Foo() {
(function() {
this.b = 789;
})();
(function() {
alert(this.b); // 789
alert(b); // 789
var a = 0;
alert(a); // 0
})();
}
var f = new Foo();
(function() {
alert(this.b); // 789
alert(b); // 789
})();
②
function Foo() {
(function() {
this.b = 789;
})();
(function() {
alert(this.b); // 789
alert(b); // undefined
var b = 0;
alert(b); // 0
})();
}
var f = new Foo();
(function() {
alert(this.b); // 789
alert(b); // 789
})();
以上两个对比,说明:
(1)没有加 this取值时,如果当前 {} 中不存在同名的局部变量,则等同于加 this 处理;如果当前 {} 中存在同名的局部变量,则按常规处理。
以上只是鄙人的粗浅见解,内容还不够完整,还会不断完善删改,如其中有什么错误之处还望读者谅解,真诚希望能留下您的宝贵建议,以图修改!这里欢迎每一位爱好JS的读者,真心希望能和你们交流心得!
分享到:
相关推荐
匿名函数是JavaScript语言中的一个强大特性,它允许我们不给函数命名,直接声明并执行。在本文中,我们将深入了解匿名函数的定义、特点、代码模式以及应用。 首先,需要明白什么是匿名函数。在JavaScript中,定义...
在这个例子中,`outer`函数返回了一个匿名函数,该匿名函数形成了一个闭包,可以访问并修改`outer`函数作用域内的`counter`变量。 在jQuery中,经常可以看到匿名函数的使用,尤其是在初始化代码或插件中,通过IIFE...
在JavaScript中,括号`()`用于函数调用,也可以用来创建一个表达式。在匿名函数前加`()`,如`(function() {})()`,是为了立即执行这个函数,因为JavaScript会优先处理表达式。这在创建闭包时特别有用,因为它确保...
因此,当我们在定义匿名函数后紧跟一对小括号时,实际上是在告诉JavaScript引擎:“这是一个应该立即执行的函数。” 此外,文章还提到了一些有趣的现象,比如使用`~`, `!`, `+`, `-`等运算符也可以达到相同的效果。...
在JavaScript中,根据一些流行的编码风格指南,如Airbnb Style Guide或Google JavaScript Style Guide,函数名与小括号之间应保留一个空格,以增加代码的可读性。例如: ```javascript functionName(参数1, 参数2);...
- **内部函数**:在另一个函数内部定义的函数,可以访问外部函数的变量。 - **返回函数的函数**:函数可以返回另一个函数,这种模式常用于构建更复杂的逻辑结构。 - **闭包**:当一个内部函数引用了外部函数的变量时...
在JavaScript中,我们可以使用`function`关键字来定义一个函数。基本语法如下: ```javascript function 函数名(参数1, 参数2, ...){ // 函数体,执行的代码 } ``` 例如,创建一个简单的函数`sayHello`,它接受一...
在这段代码中,`targetFunction`被定义为window对象的一个属性,然后通过`window[funcName]()`的方式调用该函数。 3. 使用对象存储函数: 当函数不是全局函数时,我们可以将函数存储在一个对象中,之后通过对象的...
函数声明会在当前作用域中创建一个全局变量,并将该变量绑定到函数对象上。 **示例:** ```javascript function myTest() { window.alert("hello"); } ``` 在这个例子中,`myTest`是一个通过函数声明定义的函数...
因为前面的表达式返回的是一个函数,所以在这个小括号后面加上一对空括号就会执行这个函数,就像我们在普通位置调用一个有名称的函数一样。 IIFE的主要用途包括: - **变量作用域**:JavaScript全局变量污染是一个...
JavaScript 函数式编程是一种编程范式,它将函数视为第一类公民,允许它们作为其他函数的参数、返回结果,甚至可以存储在变量中。在JavaScript中,函数式编程提供了更高级别的抽象,使得代码更简洁、可读性更强,...
### JavaScript中匿名函数的创建与调用方法分析 #### 一、概述 在JavaScript中,函数是一等公民,这意味着函数可以作为参数传递给其他函数,也可以作为其他函数的返回值。这种灵活性使得JavaScript中的函数非常强大...
在JavaScript中,函数是一段可执行的代码块,它能够接收参数,执行特定任务,并可能返回结果。以下是关于JavaScript函数的详细讲解: 1. **函数定义**: - 无参函数定义:`function 函数名 () { 代码... }` - 有...
在JavaScript中,我们可以直接定义一个不带名称的函数表达式,例如: ```javascript // 会报错,因为缺少分号 // function(){} // 将匿名函数赋值给变量 var fun = function() {}; // 匿名函数自执行 (function()...
或者,如果保留函数名称,通常会在函数表达式外层的括号中使用另一个括号来避免解析问题: ```javascript ((function foo() {})()); ``` 这样,`foo`作为函数表达式的名称,不会引起错误,而外层的括号确保整个...
本文将详细介绍JavaScript中匿名函数的各种调用方式及其应用场景。 #### 二、匿名函数的基础概念 匿名函数是一种没有显式名称的函数,它通常通过表达式的形式定义。匿名函数可以通过以下几种方式来调用: 1. **...
在JavaScript中,有三种主要的函数定义方式:带名函数、匿名函数和箭头函数。每种函数类型都有其特定的用途和特点。 1. **带名函数**: 带名函数在定义时有一个明显的函数名称,例如`function abs(x) {...}`。这种...
在JavaScript中,大括号用来定义一个对象。对象是包含一组键值对的数据集合,键是字符串类型,而值可以是任何数据类型。在定义对象时,键和值之间使用冒号":"分隔,键值对之间使用逗号","分隔。例如: ```...
14. **函数柯里化(Currying)**:将一个多参数的函数转化为一系列单参数的函数,每个函数返回一个新的函数,直到所有参数都被处理。常用于创建更灵活的函数接口。 15. **函数绑定(Bind)**:`Function.prototype....