函数,作用域,预解析,沙箱模式

函数

函数基础

重复代码、冗余代码的缺点:

  1. 代码重复,可阅读性差

  2. 不易维护,如果代码逻辑改变了,所有地方的代码都要跟着改变,效率太低。

函数的声明与调用

声明函数的语法:

1
2
3
function 函数名(){
//函数体
}

调用函数的语法:

1
函数名();

特点:

1
2
1. 函数声明的时候,函数体并不会执行,函数体只有在调用的时候才会执行,
2. 可以调用多次

函数的参数

  1. 形参(形式参数):在函数声明时,设置的参数。作用是占位置。
  2. 实参(实际参数):在函数调用时,传入的参数。作用:函数调用时,会把实参的值赋值给形参,这样形参就有了值。

语法:

1
2
3
4
5
6
7
//带参数的函数声明
function 函数名(形参1, 形参2, 形参...){
//函数体
}

//带参数的函数调用
函数名(实参1, 实参2, 实参3);

注意:

  • 形参在声明时,值不固定,只有在调用的时候,形参的值才确定,形参的值会跟着函数调用时的实参不一样而不一样。
  • 如何确定形参:在声明函数的时候,碰到不确定的值的时候,就可以定义成形参。

函数的返回值

当函数执行完的时候,我们期望函数给我一些反馈(比如计算的结果),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个返回值

返回值语法:

1
2
3
4
5
6
7
8
//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参...){
//函数体
return 返回值;
}

//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3);

注意:

  • 函数的调用结果就是返回值,因此我们可以直接对函数调用结果进行操作。

函数三要素

函数三要素包括:函数名、参数、返回值

1
2
3
function getArea (r) {
return Math.PI * r * r;
}

函数高级

函数调试

断点调试:

1
2
3
4
F8:跳到下一个断点,如果后面没有断点了,那么代码直接执行完。
F10:单步调试(跳过函数调用)
F11:单步调试(进入函数调用)
shift+F11:跳出函数调用

函数内部可以调用函数

1
2
3
4
5
6
7
8
9
10
11
12
13
function fn1() {
console.log("fn1开始...");
fn2();
console.log("fn1结束...");
}

function fn2 () {
console.log("执行fn2的代码");
console.log("执行fn2的代码");
console.log("执行fn2的代码");
}
//在函数1中调用了函数2
fn1();

全局变量与局部变量

全局变量:在最函数外,script标签内声明的变量就是全局变量,全局变量在任何地方都能访问的到。

局部变量:在函数中声明的变量,就是局部变量,局部变量只有在当前函数体内能够访问。

隐式全局变量:没有使用var定义的变量也是全局变量。

1
2
3
4
5
6
7
var num = 11;//全局变量
function fn() {
var num1 = 22;//局部变量
num2 = 33;//隐式全局变量
console.log(num1);
}
fn();

变量的查找规则:

  • 自己有就用自己的,自己没有就用外面的。
1
2
3
4
5
6
7
var num = 11;
function fn() {
var num = 22;
console.log(num);//22
}
fn();
console.log(num);//11

预解析

js执行代码分为两个过程:

  • 预解析过程(变量与函数提升)
  • 代码一行一行执行

预解析过程:

  1. 函数优先,先提升function,后提升var
  2. 遇到重名的var会被忽略。
  3. 遇到重名的function会被覆盖。

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//1. 
var num = 10;
fn1();
function fn1() {
console.log(num);
var num = 20;
}

//2.
var a = 18;
fn2();
function fn2() {
var b = 9;
console.log(a);
console.log(b);
}

//3.
fn3();
console.log(c);
console.log(b);
console.log(a);
function fn3() {
a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}

声明函数的两种方式

函数声明(命名函数):

1
2
3
function 函数名(){
//函数体
}

函数表达式(匿名函数):

1
2
3
var 函数名 = function(){
//函数体
}

这两种函数声明的区别:

  1. 命名函数可以先调用,在声明,因为预解析
  2. 函数表达式必须先声明,再调用(在DOM中注册事件的时候用的非常的多)

匿名函数

匿名函数:没有名字的函数

匿名函数如何使用:

1
2
1. 将匿名函数赋值给一个变量,这样就可以通过变量进行调用
2. 匿名函数自调用

自执行函数(匿名函数自调用)的作用:防止全局变量污染。