JavaScript学习笔记(九) 函数的基本知识和专业术语

掌握函数对JavaScript程序猿来说是个基本功,因为JavaScript的函数有很多用法;

接下来,我们会学习不同的方法去定义函数,你会学到函数表达式和函数声明;

你会看到局部作用域(local scope)和变量提升(hoisting)是如何工作的;

接着我们会学习一些模式去帮助我们改善我们的API(更好的编程接口),代码初始化过程和性能。


让我们深入探讨函数,首先从回顾和澄清非常重要的基础知识开始。

基础知识(Background)

在JavaScript中函数有两个主要的特点让它特殊化:
1.函数是一个对象;
2.函数提供作用域;
函数是对象,那么:
  • 可以在运行时动态创建,整个程序执行的过程中
  • 可以赋值给一个变量,可以持有函数的引用并复制给其他变量,可以被扩展,在一些特殊情况可以被删除(delete)
  • 可以作为一个参数传递给其它函数,也可以作为其它函数的返回值
  • 可以拥有它自己属性和方法

所以可能出现的情况,函数A是一个对象,有属性和方法,其中一个恰巧是函数B,B接受一个函数C作为参数,当执行结束后,返回另一个函数D;

乍看之下,需要去记住很多函数。但当你属性了函数的各种用途,你就会欣赏函数提供的能力,灵活性和表达性;

一般,当你思考JavaScript函数时,可以想象成一个对象,但唯一一个特殊的功能就是这个对象是可调用的,意味着它能被执行;

为了让函数是对象这个事实更明显一些,我们可以看new Function()构造方法的用法:

// antipattern
// for demo purposes only
var add = new Function('a, b', 'return a + b');
add(1, 2); // returns 3
这段代码中,add()是一个对象是毫无疑问的,因为它是由构造方法创建的。

虽然使用Function()构造函数不是一个好注意(和Eval()一样糟糕),因为代码作为一个字符串传入并解析;

写起来和读起来也非常不方便,你不得不去转义引号,如果你想为了更好看,在函数中适当缩进代码就要格外小心;


函数第二个重要的功能就是函数提供作用域,在JavaScript中,没有大括号的局部作用域,换言之,大括号不创建作用域,只有函数作用域;

在函数中,任何使用var定义的变量都是局部变量,在函数外是不可见的;

说大括号不创建局部作用域的意思是如何你在if或者while循环中使用var定义了一个变量,并不意味着这个变量是if或者for的局部变量;

它是外围函数(wrapping function)的局部变量,如果没有外围函数,它会成为全局变量,我们以前说过要尽可能的减少全局变量;

所以函数是控制变量作用域不可缺少的因素。


避免歧义的术语(Disambiguation of Terminology)

接下来,让我们花一些时间去讨论一下用来定义函数的术语,因为在我们讨论模式的时候,使用准确,一致的名称和代码一样重要;

看下面这段代码:

// named function expression
var add = function add(a, b) {
    return a + b;
};
这段代码通过命名的函数表达式(named function expression)展现了一个函数;

如何你省略了函数表达式的名字,你会得到一个未命名的函数表达式(unnamed function expression),被简称为函数表达式(function expression)或者更常见 的叫法匿名函数(anonymous function);

例子:

// function expression, a.k.a. anonymous function
var add = function (a, b) {
    return a + b;
};
所以函数表达式(function expression)范围更广,命名的函数表达式(named function expression)是函数表达式的一种特殊情况(定义了可选的名称);

当你省略第二个add,以未命名的函数表达式结束,这不会影响函数的定义和使用;

唯一的不同之处就是函数的name属性会是一个空字符串或者是undefined(取决于具体的实现),name属性不是语言的扩展(不是ECMA标准的一部分)但是在很多环境中广泛使用;

如果你保留第二个add,那么add.name属性将会包含字符串"add";

最后,还有函数声明(function declarations):

function foo() {
    // function body goes here
}
在语法上,命名的函数表达式和函数声明看起来非常像,不同的地方就是是否将函数表达式的结果赋值给了一个变量;

有些时候,除了查看上下文(context)没有其它办法说明函数声和命名的函数表达式的区别,我们会在以后详细说明;

还有一个语法的区别就是结尾的分号,函数声明不需要分号,但函数表达式需要;

你应该始终使用这个分号,即使自动分号插入机制可能会为你做这件事。


还有一个术语函数字面量(function literal)也经常使用,但它可能意味着未命名函数表达式或命名的函数表达式,因为这种模糊性,所以最好不要使用它。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值