首页 > 网站 > WEB开发 > 正文

JavaScript世界的一等公民—— 函数

2024-04-27 14:17:19
字体:
来源:转载
供稿:网友

javaScript世界的一等公民—— 函数

简介

在很多传统语言(C/C++/Java/C#等)中,函数都是作为一个二等公民存在,你只能用语言的关键字声明一个函数然后调用它,如果需要把函数作为参数传给另一个函数,或是赋值给一个本地变量,又或是作为返回值,就需要通过函数指针(function pointer)、代理(delegate)等特殊的方式周折一番。而在Javascript世界中函数却是一等公民,它不仅拥有一切传统函数的使用方式(声明和调用),而且可以做到像简单值一样赋值、传参、返回,这样的函数也称之为第一级函数(First-class Function)。不仅如此,JavaScript中的函数还充当了类的构造函数的作用,同时又是一个Function类的实例(instance)。这样的多重身份让JavaScript的函数变得非常重要。

一、JavaScript函数入门级

JavaScript函数像一般语言一样也是遵循先声明后使用的原则,函数名只能包含字母、数字、下划线或$,且不能以数字开头。函数常见的声明方式有以下两种:view sourcePRint?
1// 直接声明函数myfunc
2function myfunc(/* arguments */) {
3}
4
5// 把匿名函数赋值给本地变量myfunc
6var myfunc = function(/* arguments */) {
7}
注意,上面两种函数声明方式存在细微的差别:第一种方式在声明时就是一个命名的函数,无论是声明在调用之前调用之后,甚至是不会执行到的位置(例如return语句之后或是永远不会为真的分支里),都在整个作用域可访问;第二种方式是通过把匿名函数赋值给变量的方式,严格意义上说这不是一个函数的声明(function declaration)而是一个函数表达式(function expression),在赋值之前这个函数不能被任何代码访问到,也就是说这个赋值必须在调用之前完成,否则调用时会出现错误:"TypeError: undefined is not a function"。例如:view sourceprint?
1myfunc1(); // 能够正常调用,因为myfunc1采用直接声明的方式
2
3function myfunc1() {
4}
5
6myfunc2(); // 出错 TypeError: undefined is not a function
7
8var myfunc2 = function() {
9};
函数的基本调用方式与传统语言相同用一对括号调用: myfunc()。JavaScript的函数也支持直接或间接的递归(recursive)调用,例如经典的斐波那契函数用JavaScript可以这样实现:view sourceprint?
1function fib(n) {
2if (n == 1 || n == 2) {
3return 1;
4} else {
5return fib(n - 2) + fib(n - 1);
6}
7}
在JavaScript的函数可以处理变长参数,在函数内部都拥有一个名为arguments的局部变量,它是一个类数组(array-liked)的对象,里面包含了所有调用时传入的参数,有length属性表示参数的个数。例如:view sourceprint?
1function test() {
2alert(arguments.length);
3}
4
5test(1); // 1
6test(1, 'a'); // 2
7test(true, [], {}); // 3
利用arguments可以实现类似C语言printf的功能,也可以用来实现方法的多态。

二、JavaScript函数进阶

2.1 匿名函数和嵌套函数在JavaScript可以声明一个没有名称的函数,称为匿名函数(Anonymouse Function)。同时JavaScript还允许在函数内部声明函数,称为嵌套函数(Nested Function),嵌套函数的作用域为整个父函数。在前面函数声明的部分就看到了匿名函数和嵌套函数的一种用法,由于匿名函数没有名称,不会引入新的变量污染上下文环境,而且会带来新的变量作用域,因此匿名函数常被用来防止全局环境污染。JavaScript运行时中有一个特殊的全局环境(global object),这个对象上面存放全局的函数和变量,实际开发中经常会使用若干第三方的库或多个js文件,若不小心在全局对象引入重复的变量或函数声明,则会造成代码执行混乱。例如先后引入两个js文件,分别定义了自己的函数log作为内部使用,则第二引入的函数会覆盖第一个的定义且不会抛出任何错误,在后续的执行中调用log函数可能会造成错误。这时候使用一个匿名函数将整个js内的逻辑包装起来,就可以避免这种错误,这种方法已经被绝大多数开源js库使用。view sourceprint?
1(function() { // 匿名函数
2
3function log(msg) {
4console.log(msg);
<
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表