Java教程

JavaScript--函数基础知识

本文主要是介绍JavaScript--函数基础知识,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、函数的概念

函数(function)也叫做功能、方法。

函数可以将一段代码封装起来,被封装起来的函数具备某一项特殊功能,内部封装的一段代码作为一个完整的结构体(函数体),要执行就都执行,要不执行就都不执行。

2、函数的声明(定义)

函数必须先定义才能使用,否则会出现引用错误。

声明语法:

        function 函数名(参数) {

                封装的结构体;

        }

//定义函数
function fun() {
    console.log(2);
}

函数命名规则:由数字、字母、下划线、$符号组成,不能以数字为开头,区分字母大小写,不能使用关键字和保留字。

函数声明的时候,函数体并不会执行,只有函数被调用才会被执行。

3、函数调用(函数执行)

调用方法:函数名();

function fun() {
    console.log(2);
}
//调用函数
fun();

函数内部语句执行的位置,与函数定义的位置无关,与函数调用的位置有关。

函数可以一次定义,多次调用执行。

4、函数的参数

接口:就是函数的参数,函数的参数本质是一个变量,可以接收任意类型的数据,导致函数执行结果根据参数不同,结果也不同。

一个函数可以设置 0 个或者多个参数,多个参数之间用逗号分隔。

函数的参数根据书写位置不同,名称也不同:

形式参数:定义()内部的参数,叫形式参数。本质是变量,可以接收实际参数传递过来的数据,简称形参。

实际参数:调用()内部的参数,叫实际参数。本质就是传递的各种类型的数据,传递给每个形参,简称实参。

function fun(a,b) { // 小括号中的a,b为形式参数
    console.log(a,b);
}
//调用函数
fun(4,5);// 小括号中的4,5为实际参数

函数执行过程中,伴随传参过程:

一般自己封装的函数或者其他人封装的函数需要有一个API接口说明,告诉用户参数需要传递什么类型的数据,实现什么功能

// 定义一个求和函数,传入两个参数
// 参数:传两个参数,数据类型为数字
// 功能:得到两个数字之和
function sum(a,b) {
    console.log(a + b);
}
// 调用函数中,给小括号内部添加数据
sum(3,4);
sum("3",4);

5、函数的返回值

利用函数内部的一个return的关键字设置函数的返回值。

作用-1:函数内部如果结构体执行到一个return的关键字,会立即停止后面代码的执行

// return 可以终止函数的执行
function sum() {
    console.log(1);
    console.log(2);
    console.log(3);
    return;
    console.log(4);
    console.log(5);
    console.log(6);
}
// 调用函数
sum();

作用-2:可以在return关键字后面添加空格,空格后面而已定义一个数据字面量或者表达式,函数在执行完自身功能之后,整体会被return爱化成一个表达式,表达式必须求出一个值继续可以参与程序,表达式的值就是return后面的数据

// 使用返回值,制作函数运行结果后的结果
function fun(a,b) {
    return a + b;
}
// 调用函数
console.log(fun(3,4));

返回值应用:

函数如果有返回值,执行结果可以当成普通数据参与程序;或者可以作为一个普通数据赋值给一个变量,甚至赋值给其他函数的实参

// 使用返回值,制作函数运行结果后的结果
function fun(a,b) {
    return a + b;
}

// 调用函数
console.log(fun(3,4));

// 将返回值赋值给变量
var num = fun(3,4);
console.log(num);

// 将返回值赋值给函数的实参
console.log(fun(2,fun(3,4)));

注意:函数没有设置return语句,那么函数返回值是undefined;设置return,但是return后面没有值,默认返回值也是undefined。

6、函数表达式

是函数的另一种定义方式

定义方法:将函数的定义、匿名函数(没有函数名)赋值给一个变量

调用函数表达式,方法是给变量名加()执行,不能使用函数名加()执行

// 定义一个函数表达式
var foo = function fun() {
    console.log(1);
};

// 实际采用方式,因为在调用是使用的是变量名
var foo2 = function() {
    console.log(2);
};

// 调用函数式,只能用变量名调用,函数名调用不成功
foo();
foo2();

7、函数的数据类型

函数是一种单独的数据类型function。可以参与其他程序

如:

  • 可以把函数作为另一个函数的参数,在另一个函数中调用
// 函数是一种数据类型,可以当成其他函数的参数
setInterval(function() {
    console.log(1);
}, 1000);
  • 可以将函数当成另一个函数的返回值
// 将函数当成另一个函数的返回值
function fn(b) {
    var a = 10;
    return function() {
        alert(a + b); 
    }
}

8、arguments对象(函数的内置属性)

所有函数都内置了一个arguments对象。arguments对象中存储了传递的所有实参。

arguments是一个伪数组,因此可以进行遍历。

函数的实参与形参个数可以补贴,所有的实参都存储在arguments对象中。

// 调用函数的时候,实参的个数可以与形参不同

//函数内部有一个 arguments 对象,会接收所有的实参
function fun() {
    console.log(arguments);
    console.log(arguments.length);
    // 使用数组遍历方法可以获取每一项实参
    for(var i = 0; i <= arguments.length-1; i++) {
        console.log(arguments[i]);
    }
}

// 调用函数
fun(1,2,3,4,5,6,7);

案例应用:定义一个求和函数,如果传入1个参数,返回它自己,如果传入两个参数,返回他们的和,如果传入三个参数,先比较前两个的大小,大的与第三个参数求和返回,如果传入四个及以上,输出错误提示。

function sum(a,b,c) {
    // 条件分支语句,根据实参个数走不同的分支
    switch (arguments.length) {
        case 1:
            return a;
            break;
        case 2:
            return a + b;
            break;
        case 3:
            return a > b ? a + c : b + c;
            break;
        default:
            // 提示用户实参个数传递错误
            // 模拟控制台报错
            throw new Error("参数个数不能超过 3 个");
    }
}
// 调用函数
console.log(sum(1));
console.log(sum(1,2));
console.log(sum(1,2,3));
console.log(sum(1,2,3,4,5));

9、函数递归

函数内部可以通过函数名调用函数自身的方式,叫做函数递归。

更多时候,使用递归去解决一些数学中的现象。函数递归次数太多,会出现错误:超出计算机最大计算能力

/* 函数,如果我们传入的参数是 1 ,返回 1 ,如果传入的是 1 以上的
数字,让它返回参数 + 函数调用上一项 */
function fun(a) {
    if (a === 1) {
        return 1;
    } else {
        return a + fun(a - 1);
    }
}
// 调用函数
console.log(fun(1));
console.log(fun(2));
console.log(fun(3));

console.log(fun(100000000000)); //报错:超出计算机最大计算能力

案例应用:输出斐波那契数列的某一项的值

// 菲波那切数列:后面的一项数据是前两项数据之和。1、1、2、3、5、8、13、21、34、55、、、
// 参数:正整数
// 返回值:对应的整数位置的菲波那切数列的值
function fibo(a) {
    // a 表示项数
    if (a === 1 || a === 2) {
        return 1;
    } else {
        // 返回 前一项 和 前前一项
        return fibo(a - 1) + fibo(a -2);
    }
}
// 调用函数
console.log(fibo(1));
console.log(fibo(2));
console.log(fibo(3));
console.log(fibo(4));
console.log(fibo(5));

10、作用域:变量可以起作用的范围

如果定义一个变量在函数内部,只能在函数内部被访问到,在函数外部不能使用这个变量,函数就是变量定义的作用域。

局部变量:定义在函数内部的变量,只能在函数作用域内被访问到。

全局变量:从广义上来说,也是一种局部变量,定义在全局的变量,作用域范围是全局,在整个JavaScript程序任意位置都能够被访问到。

// 定义函数
function fun() {
    var a = 1;
    console.log(a);
}
// 执行函数
fun();
// 函数外部调用 a
console.log(a); //不成功


// 函数的参数也是局部变量
function sum(a) {
    a = 2;
    console.log(a);
}
// 调用函数
sum(1);
console.log(a); //不成功

// 函数也有自己的作用域
function outer() {
    var a = 1;
    function inner() {
        console.log(2);
    }
    // 函数内部调用子函数才能成功
    inner();
}
// 调用函数
outer();
inner(); // 错误方式 定义范围在函数内部

局部变量退出作用域之后被销毁,全局变量关闭网页或者浏览器才会被销毁。

函数参数也是局部变量, 只能在函数内部被使用,在函数外面没有定义。

函数也有自己的作用域,定义在哪个作用域内部,只能在这个作用域范围内被访问,出了作用域不能被访问的。 函数定义在另一个函数内部,如果外部函数没有执行时,相当于内部代码没写。

11、作用域链

 将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。

function f1() { 
    function f2() {

    } 
} 

var num = 456; 

function f3() { 
    function f4() {

    } 
}

图示:

遮蔽效应:程序在遇到一个变量时,使用时作用域查找顺序,不同层次的函数内都有可能定义相同名 字的变量,一个变量在使用时,会优先从自己所在层作用域查找变量,如果当前层没有变 量定义会按照顺序从本层往外依次查找,直到找到第一个变量定义。整个过程中会发生内 层变量遮蔽外层变量的效果,叫做“遮蔽效应。

// 全局作用域
var a = 1;
// 创建函数
function outer() {
    var a = 2;
    // 内部函数
    function inner() {
        var a = 3;
        console.log(a);
    }
    inner();
}
// 调用
outer();

不写var关键字的影响

在函数内部想要定义新的变量,如果不加关键字var,相当于定义的全局变量,如果全局也有相同的标识符,会被函数内部的变量影响,局部变量污染全局变量,所以每次定义变量是都必须写var关键字。

12、预解析

 JavaScript 代码的执行是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器执行 JavaScript 代码的时候,分为两个过程:预解析过程和代码执行过程

预解析过程:

        1. 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。

        2. 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。

        3. 先提升 var,再提升 function。

JavaScript 的执行过程:在预解析之后,根据新的代码顺序,从上往下按照既定规律执行 js 代码。

提升顺序:

  • 预解析过程中,先提升 var 变量声明,再提升 function 函数声明。
  • 假设出现变量名和函数名相同,那么后提升的函数名标识符会覆盖先提升的变量名,那 么在后续代码中出现调用标识符时,内部是函数的定义过程,而不是 undefined。
  • 如果调用标识符的过程在源代码函数和变量定义后面,相当于函数名覆盖了一次变量名, 结果在执行到变量赋值时,又被新值覆盖了函数的值,那么在后面再次调用标识符,用 的就是变量存的新值。
  • 建议:不要书写相同的标识符给变量名或函数名,避免出现覆盖。

 函数表达式进行的是变量声明提升,提升后变 量内部存的是一个 undefined。在前面进行函数方法调用,数据类型会提示错误。 建议:定义函数时,最好使用 function 关键字定义方式,这样函数声明提升可以永远生效。

// 预解析 把变量、函数声明部分提升到了作用域最顶部
//模拟提升
// var a; // 相当于存储了一个undefined的值
// function fun() {
//     console.log(2);
// }
// 调用一个变量
console.log(a);
console.log(fun);
// 后定义变量
var a = 1;
// a = 1;
var fun = "haha";
//先调用函数
fun();
// 定义函数
function fun() {
    console.log(2);
}
// 调用
fun();


foo();
// 函数表达式进行的是变量声明提升
var foo = function () {
    console.log(a);
}

13、 IIFE 自调用函数

 IIFE:immediately-invoked function expression,叫做即时调用的函数表达式,也叫做自调用函数,表示函数在定义时就立即调用。

 函数调用方式:函数名或函数表达式的变量名后面加 () 运算符。

 函数矮化成表达式的方法,可以让函数参与一些运算,也就是说给函数前面加一些运算符。

        数学运算符:+ - ()

        逻辑运算符:!非运算

//关键字定义的方式,不能立即执行
// function fun() {
//     console.log(1);
// }();

//函数表达式方式,可以在定义是被立即执行
var foo = function () {
    console.log(2);
}();


//通过在函数前面添加操作符,可以讲函数矮化成表达式
+ function fun() {
    console.log(1);
}();
- function fun() {
    console.log(1);
}();
(function fun() {
    console.log(1);
})();
!function fun() {
    console.log(1);
}();
// IIFE 关注了函数的作用域,在外面是调用不了函数的 fun();

//常用的IIFE结构
(function(a){
    console.log(a);
})(4);

 IIFE 结构可以关住函数的作用域,在结构外面是不能调用函数的。

 IIFE 最常用的是 () 运算符,而且函数可以不写函数名,使用匿名函数。

这篇关于JavaScript--函数基础知识的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!