转载:http://www.nowamagic.net/librarys/veda/detail/1663
函数表达式(缩写为FE)是这样一种函数:
- 在源码中须出现在表达式的位置
- 有可选的名称
- 不会影响变量对象
- 在代码执行阶段创建
这种函数类型的主要特点在于它在源码中总是处在表达式的位置。最简单的一个例子就是一个赋值声明:
1 |
var foo = function () {
|
2 |
...
|
3 |
}; |
该例演示是让一个匿名函数表达式赋值给变量foo,然后该函数可以用foo这个名称进行访问——foo()。
同时和定义里描述的一样,函数表达式也可以拥有可选的名称:
1 |
var foo = function _foo() {
|
2 |
...
|
3 |
}; |
需要注意的是,在外部FE通过变量“foo”来访问——foo(),而在函数内部(如递归调用),有可能使用名称“_foo”。
如果FE有一个名称,就很难与FD区分。但是,如果你明白定义,区分起来就简单明了:FE总是处在表达式的位置。在下面的例子中我们可以看到各种ECMAScript 表达式:
1 |
// 圆括号(分组操作符)内只能是表达式 |
2 |
( function foo() {});
|
3 |
|
4 |
// 在数组初始化器内只能是表达式 |
5 |
[ function bar() {}];
|
6 |
|
7 |
// 逗号也只能操作表达式 |
8 |
1, function baz() {};
|
表达式定义里说明:FE只能在代码执行阶段创建而且不存在于变量对象中,让我们来看一个示例行为:
1 |
// FE在定义阶段之前不可用(因为它是在代码执行阶段创建) |
2 |
alert(foo); // "foo" 未定义
|
3 |
( function foo() {});
|
4 |
|
5 |
// 定义阶段之后也不可用,因为他不在变量对象VO中 |
6 |
alert(foo); // "foo" 未定义
|
相当一部分问题出现了,我们为什么需要函数表达式?答案很明显——在表达式中使用它们,”不会污染”变量对象。最简单的例子是将一个函数作为参数传递给其它函数。
01 |
function foo(callback) {
|
02 |
callback();
|
03 |
} |
04 |
|
05 |
foo( function bar() {
|
06 |
alert( 'foo.bar' );
|
07 |
}); |
08 |
|
09 |
foo( function baz() {
|
10 |
alert( 'foo.baz' );
|
11 |
}); |
在上述例子里,FE赋值给了一个变量(也就是参数),函数将该表达式保存在内存中,并通过变量名来访问(因为变量影响变量对象),如下:
1 |
var foo = function () {
|
2 |
alert( 'foo' );
|
3 |
}; |
4 |
|
5 |
foo(); |
另外一个例子是创建封装的闭包从外部上下文中隐藏辅助性数据(在下面的例子中我们使用FE,它在创建后立即调用):
01 |
var foo = {};
|
02 |
03 |
( function initialize() {
|
04 |
var x = 10;
|
05 |
foo.bar = function () {
|
06 |
alert(x);
|
07 |
};
|
08 |
})(); |
09 |
|
10 |
foo.bar(); // 10;
|
11 |
alert(x); // "x" 未定义
|
我们看到函数foo.bar(通过[[Scope]]属性)访问到函数initialize的内部变量“x”。同时,“x”在外部不能直接访问。在许多库中,这种策略常用来创建”私有”数据和隐藏辅助实体。在这种模式中,初始化的FE的名称通常被忽略:
1 |
( function () {
|
2 |
// 初始化作用域
|
3 |
})(); |
还有一个例子是:在代码执行阶段通过条件语句进行创建FE,不会污染变量对象VO。
1 |
var foo = 10;
|
2 |
|
3 |
var bar = (foo % 2 == 0
|
4 |
? function () { alert(0); }
|
5 |
: function () { alert(1); }
|
6 |
); |
7 |
|
8 |
bar(); // 0
|
相关推荐
4. **函数与表达式**:介绍了一系列内置函数,如字符串函数、日期函数和数学函数,以及如何创建自定义函数,以增强SQL查询的灵活性和功能性。 5. **数据更新与插入**:讨论了INSERT、UPDATE和DELETE语句的使用,...
10. **Lambda表达式和函数式编程**:Java 8引入了lambda表达式,简化了匿名内部类的使用,使得函数式编程风格成为可能。理解函数式接口、Stream API和并行流的概念,能写出简洁高效的代码。 以上知识点只是《Java...
11. **Lambda表达式**:自Java 8开始引入,Lambda简化了函数式编程,使得代码更加简洁。 12. **模块系统**:Java 9引入的模块系统(Jigsaw项目)有助于组织大型项目,提高代码的封装性和可维护性。 这份"Java解惑...
10. **Lambda表达式**:Java 8引入的新特性,简化了函数式编程,使得处理集合数据变得更加简洁。 11. **Optional类**:用于表示可能为null的值,帮助避免空指针异常,但过度使用也可能导致代码复杂性增加。 12. **...
10. **Java 8及更高版本的新特性**:如Lambda表达式、函数式编程、Stream API等,这些都是现代Java开发的重要组成部分。 11. **并发编程工具**:如ConcurrentHashMap、ExecutorService、CountDownLatch等,它们在多...
I/O流用于读写文件和网络通信,网络编程则涉及Socket和ServerSocket,反射允许我们在运行时动态地访问类的信息,注解可以提供元数据,泛型提高了代码的类型安全,Lambda表达式和Stream API简化了函数式编程。...
除此之外,本书可能还会讨论一些现代Java开发的热点话题,比如Java 8及更高版本的新特性,如Lambda表达式、函数式编程、Stream API等。这些新特性的介绍将帮助开发者保持与时俱进,适应不断发展的技术环境。 总之,...
9. **Lambda表达式**:自Java 8开始,引入了Lambda表达式,简化了函数式编程,尤其是在处理集合和事件驱动编程时。 10. **模块化系统**:Java 9引入了模块系统,通过明确的模块依赖关系,增强了程序的可维护性和可...
最后,书中还会涉及一些高级主题,如模板、STL(标准模板库)、以及C++11及后续版本的新特性,如智能指针、lambda表达式等,帮助读者跟上C++的发展步伐。 通过阅读《C++编程初学者入门解惑》,初学者可以系统地学习...
最后,对于Java的最新版本,如Java 8、9、11及以上,书中可能会涵盖新特性,如Lambda表达式、函数式编程、Stream API、模块系统等,这些都是现代Java开发的关键组成部分。 总的来说,《Java解惑(中文)》这本书...
面试官可能会询问关于构造函数、访问修饰符、接口、抽象类的区别,以及如何利用OOP设计原则来解决问题。 2. **异常处理**:理解Java异常处理机制,包括try-catch-finally语句块、检查型异常与运行时异常的区别、...
观察法是直接从函数表达式中找出值域的规律,例如2y=x+2的值域为全体实数R。换元法则是通过变量替换简化原函数,例如222yxx可以设t=x^2,转换成关于t的函数求解。利用函数性质或图像是通过分析函数的增减性、...
【Java解惑很全的题目】是一份专为Java学习者设计的疑难解答文档,它包含了一系列关于Java编程语言的问题和谜题,旨在帮助读者深入理解Java的核心概念、语法特性和编程技巧。以下是对其中部分题目及其涉及知识点的...
要能够创建和使用类,以及理解类的构造函数、方法重载和覆盖、访问修饰符(public、private、protected、默认)。 3. **异常处理**:理解如何使用try-catch-finally语句块来捕获和处理异常,以及不同的异常类层次...
13. **Lambda表达式**:Java 8引入的Lambda表达式简化了函数式编程,理解其语法和使用场景,可以写出更简洁的代码。 14. **模块化系统(Jigsaw)**:Java 9引入的模块系统提高了程序的可维护性和性能,理解模块的...
12. **Lambda表达式与函数式编程**:Java 8引入了Lambda表达式,简化了匿名函数的写法,同时函数式接口和Stream API使得函数式编程风格在Java中成为可能。 以上只是部分Java知识的概述,"Java解惑"这本书很可能深入...