除去第三章说的 var 申明一个变量外,还可以用
function
申明一个函数对象
function foo(){}
function
,见名知意就是函数,既然是函数就可以用来运算。比如最简单的加法
function add(a,b){
var result = a+b;
return result ;
}
先说一下函数的主体结构。
-
function
申明接下来是一个函数对象 -
add
说明了这个函数的名称,如果不写就是一个匿名函数 <anonymous> -
()
代表这个函数的参数部分 -
a、b
在参数部分有两个参数,分别是a和b,如果没有参数就省略4,但是3还是要保留。 -
{ }
这里不是对象{}
,而代表的是函数的主体内容。 -
var result = a+b;
实际分解为:
var result;
result = a+b;
-
return
是这个函数结尾的部分,返回后面跟随的执行结果result。假如这个函数没有返回值可以不写。
调用该add函数时,使用
add(1,2);
就会得到结果 3 。
作用域和变量提升
在函数里面有一个作用域【scope】[1]的概念,同时还有一个var
关键字的变量提升,变量提升和作用域是息息相关的。
其实变量提升我已经写下来了,反观add第六步,就是变量提升分解示意。
变量提升后的完整的第六步:
function add(a,b){
var result;
result = a+b;
return result ;
}
变量提升将变量的申明部分提升到作用域(函数体)的顶部,也就是执行时函数体的第一条语句。
为什么会有这种操作?这是因为js语言设计缺陷,允许不申明就使用:
s = 1;
直接的赋值,并没有用var或者function声明这个s。这在别的语言中,很显然是不符合先申明再使用的规范的。并且,没有申明直接使用的变量他的作用域不是当前的函数体,而是顶级的宿主对象[2],存在变量的作用域提升,会给开发者造成不必要的问题。所以,为了防止这种现象,在作用域顶部,引入 'use strict'
严格模式,严格检查当前作用域未申明的情况。
function sub(){
'use strict'
s = 1;
}
在调用 sub函数是就会报引用错误 ReferenceError: s is not defined
引申:在函数式编程中,提出了“函数是一等公民”的思想,强调函数式编程的纯净[3]
不能不说 this
默认情况下,this指向当前函数的拥有者。
在浏览器下:
function owner(){
return this;
}
owner() ;// Window
即使这个函数写在另一个函数体内
function owner(){
return function(){
return this;
};
}
owner()() ;// Window
重要的 arguments
js的函数在执行时,所有的参数列表都是由arguments这个内置属性管控的,所有的参数列表都是可以通过arguments来取值。
function argsTest(){
return arguments.length;
}
argsTest(1,2,3) // 3
argsTest(1,2) // 2
argsTest() // 0
这样做是因为js并不能函数重载[4],同名函数只能定义一次,多次定义之后就会直接覆盖:
function reloadFn(){}
function reloadFn(name){}
其实这个可以看作
var reloadFn;
reloadFn = function(){}
reloadFn = function(name){}
所以只会保留最后一次定义的值,这样就不难理解了。因此对于js来说没有重载的必要,但是又想实现重载的功能,所以就有了arguments。
arguments本身是一个类似数组,但是没有数组的某些函数。不过可以通过 Array.prototype.slice.call(arguments) 重新构建一个数组。这样,就可以当作数组来