# 函数声明与调用
# 什么是函数?
函数:将完成某一特定功能的代码封装起来,并且可以重复调用的代码块。
为何使用函数?
- 能够对代码进行复用:只要定义一次代码,就可以多次使用它。
- 能够多次向同一函数传递不同的参数,以产生不同的结果。
- 使程序更加简洁、具有逻辑性、维护方便
# 函数声明方式
# function关键字
function 函数名([参数1],[参数2],...[参数n]){
函数体
[retrun] //返回值
}
# 字面量定义(匿名函数)
var 变量 = function ([参数1],[参数2]....){
函数体
[retrun] //返回值
}
# 实例化构造函数
var 变量 = new Function([参数1],[参数2]...,"函数体");
# 函数调用方式
# 通过括号调用
用于具名函数的调用
- 函数名()
- 变量名()
function fun1(){}
fun1()
var fun2 = function (){}
fun2()
# 自调用(IIFE)
用于匿名函数的调用,匿名函数还可以通引用变量来调用。
//第一种
(function (){})()
//第二种
!function(){
}()
//第三种
(function(){
}())
注意: 在进行函数自调用时,上一条语句必须结尾有
;
# 通过事件调用
<script>
function fun(){}
</script>
<div onclick="fun()"></div>
# 注意事项
创建/调用函数注意问题:
- 如果两个函数的命名相同,后面的将会覆盖前面的函数。
- 以function声明的函数可以前置调用,以字面量方式声明方式后置调用。
- 在不同的
<script></script>
块中声明函数,声明之后块中调用。
# 问题1:函数声明覆盖
如果两个函数的命名相同,后面的将会覆盖前面的函数。
function bb(){
alert("这是第一个声明");
}
function bb(){
alert("这是第二个声明");
}
bb(); //结果为 “这是第二个声明
# 问题2:函数调用顺序
以基本语法声明的函数,会在页面载入的时候提前解析到内存中,以便调用。所以可以在函数的前面调用。但是以字面量形式命名的函数,会在执行到他的时候,才进行赋值。所以只能在函数的后面调用。
aa(); // 结果为 弹出 1
function aa(){
alert(1)
}
aa(); // 结果为 弹出 1
aa(); // 报错 aa is not a function
var aa = function(){
alert(1)
}
aa();
# 问题3:函数在不同块调用顺序
在不同的<script></script>
块中,因为浏览器解析的时候是分块解析的,所以前面的块不能调用后面块的函数,所以在不同的块之间调用函数的时候,应该先定义后调用。
<script>
aa(); //报错
</script>
<script>
function aa(){
alert(1)
}
</script>
<script>
aa() //结果为 弹出 1
</script>
# 箭头函数 ES6
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
# 箭头函数语法
箭头函数表达式的语法比普通函数表达式更简洁。
(参数1, 参数2, …, 参数N) => { 函数声明 }
(参数1, 参数2, …, 参数N) => 表达式(单一)
// 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
当只有一个参数时,圆括号是可选的:
(单一参数) => {函数声明}
单一参数 => {函数声明}
没有参数的函数应该写成一对圆括号:
() => {函数声明}
# 没有局部this的绑定
TIP
和一般的函数不同,箭头函数不会绑定this。 或者说箭头函数不会改变this本来的绑定。它没有自己的this对象,内部的this就是定义时上层作用域中的this。也就是说,箭头函数内部的this指向是固定的,相比之下,普通函数的this指向是可变的。
# 箭头函数需要注意的点
- 箭头函数没有自己的this对象。
- 不可以当作构造函数,也就是说,不可以对箭头函数使用new命令,否则会抛出一个错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
- 不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
# 不适用场合
由于箭头函数使得this从“动态”变成“静态”,下面两个场合不应该使用箭头函数。
- 第一个场合是定义对象的方法,且该方法内部包括this。
const cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
上面代码中,cat.jumps()方法是一个箭头函数,这是错误的。调用cat.jumps()时,如果是普通函数,该方法内部的this指向cat;如果写成上面那样的箭头函数,使得this指向全局对象,因此不会得到预期结果。这是因为对象不构成单独的作用域,导致jumps箭头函数定义时的作用域就是全局作用域。