JavaScript基础Day04
文章目录
一、函数
1. 函数的定义
把一段独立的具有特定功能的代码封装起来,形成一个独立实体,就是函数(封装一段代码,方便后续使用)。
2. 函数声明
```
function 函数名() {
//函数体
}
```
3. 函数表达式
```
var fn = function 函数名() {
//函数体
}
```
4. 函数调用
函数名();
-
函数在声明时不会执行,只有调用的时候才会执行,并且可以调用多次。
- demo01:判断一个数是否是素数
var num = parseInt(prompt("请输入一个数(大于1的自然数):")) function isPrime(num) { for (var i = 2; i < num; i++) { //如果有一个数是num的因子,那么输入的数就不是素数 if (num % i == 0) { return false; } } return true; } console.log(isPrime(num) ? "是素数" : "不是素数");
5. 函数的参数
- 形参:在声明一个函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值。我们可以给函数设置参数。这个参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。
- 实参:如果函数在声明时,设置了形参,那么在函数调用的时候就需要传入对应的参数,我们把传入的参数叫做实际参数,也叫实参。
6. 函数的返回值
- 当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果返回进行后续的运算),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个返回值。
- 如果函数没有显式的使用return语句,那么函数的默认返回值是:undefined;
- 如果函数使用了return语句,但是没给return值,那么函数的返回值还是undefined;
- 函数如果使用了return语句,这个函数在执行完return语句之后停止并立即退出,也就是return后面的其他代码都不会再执行。
- demo02:求一个数的阶乘
function factorial(num) {
var result = 1; //变量记得写在函数体中
for (var i = 1; i <= num; i++) {
result *= i;
}
return result; //一定不要忘记返回值
}
console.log(factorial(5)); //结果:120
- demo03:求一个数的阶乘和(1!+2!+…+n!)
function factorialSum(num1) {
var sum = 0; //变量记得写在函数体中
for (var i = 1; i <= num1; i++) {
sum += factorial(i); //需要调用demo02的阶乘函数factorial(num)
}
return sum;
}
console.log(factorialSum(3)); //结果:9 = 1+1*2+1*2*3
7. arguments的使用
在JavaScript中,arguments对象是一个比较特殊的对象,实际上是当前函数的一个内置属性,也就是说所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有的实参。arguments是一个伪数组,因此及可以进行遍历。
- demo04:计算数组中数的和
function getSum(arguments) {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(getSum([10, 20])); //结果:30
8. 案例
- demo05:求斐波那契数列Fibonacci中的第n个数是多少? (1 1 2 3 5 8 13 21…)
function getFib(num) {
var num1 = 1;
var num2 = 1;
for (var i = 3; i <= num; i++) {
var sum = num1 + num2; //分析:数列的规律是,前两个数之和正好是后一个数
num1 = num2;
num2 = sum;
}
return sum;
}
console.log(getFib(6)); //结果:8
- demo06:反转数组
function reverseArr(arr) {
for (var i = 0; i < arr.length/2; i++) { //注意:arr.length/2
var tmp = arr[i]; //先把当前书存入临时变量中
arr[i] = arr[arr.length - 1 - i]; //当前数和数组中的倒数相同位置值交换,arr.length-1-i是下标,所以记得-1
arr[arr.length - 1 - i] = tmp; //完成交换值
}
return arr;
}
console.log(reverseArr([10, 20, 30, 40])); //结果[40, 30, 20, 10]
二、作用域
1. 全局变量和局部变量
- 全局变量:在任何地方都可以访问到的变量,对应全局作用域
- 局部变量:只在固定的代码片段中能访问到的变量,最常见的例如函数内部。对应局部作用域
- 不使用var声明的变量是全局变量
2. 作用域链
只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。将这样的所有的作用域列出来,可以有一个结构:函数内指向函数外的链式结构。就称作作用域链。
- demo07:
function f1() {
function f2() {
}
}
var num = 456;
function f3() {
function f4() {
}
}
三、预解析
JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程。
预解析的过程:
-
(1) 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值;
-
(2) 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用;
-
(3) 先提升var,再提升function。
- demo08:
var a = 25;
function abc() {
alert(a); //undefined:下一行的a变量声明提前
var a = 10;
}
abc();
// 如果变量和函数同名的话,函数优先
console.log(a); //25:第一行的var a = 25;a是全局变量
function a() {
console.log('aaaaa');
}
var a = 1;
console.log(a); //1
- demo09:练习变量提升
// 1、-----------------------------------
var num = 10;
fun();
function fun() {
console.log(num); //undefined:var num提前,但是没有赋值
var num = 20;
}
//2、-----------------------------------
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a); //undefined
console.log(b); //9
var a = '123';
}
// 3、-----------------------------------
f1();
console.log(c); //9
console.log(b); //9
console.log(a); //报错:a是函数的局部变量,而b、c没有用var声明所以是全局变量
function f1() {
var a = b = c = 9;
console.log(a); //9
console.log(b); //9
console.log(c); //9
}