zl程序教程

您现在的位置是:首页 >  前端

当前栏目

JavaScript基础(三)函数、作用域

JavaScript基础 函数 作用域
2023-09-14 09:12:48 时间

目录

一、函数

1. 系统函数

2. 自定义函数的创建

3. 递归

4. 匿名函数

二、作用域


一、函数

        函数是一个功能体,提供若干个数据,返回处理结果用于封装重复执行的代码。有系统函数自定义函数之分。

1. 系统函数

  • 转数值 Number ( );
  • 转整型 praseInt ( );
  • 转浮点型 parseFloat ( );
  • 警示框 alert ( );
  • 输入款 prompt ( );

isNaN :检测一个值是否为NaN,用于检测用户输入的值是否为数值型。执行过程中,会隐式将数据转换为数值型,是NaN(不是数字)则返回true,否则返回false。

isFinite:检测一个值是否为有限值,只有无穷(infinity)是无限值。是有限值返回true,不是有限值返回false。

eval ( ) :执行字符串中的表达式。  

2. 自定义函数的创建

(1)创建普通函数

//格式:
function 函数名称 ( ) { 
    函数体
}

//调用方式:
函数名();

         PS:函数体就是封装的重复执行的代码;创建函数以后,函数体的代码不会执行,函数每调用一次,代码才会执行一次。

(2)创建带有参数的函数

//格式:
function 函数名称 (参数列表) {  //此处参数用于接收外部传递的数据(形参)
    函数体
}

//调用方式:
函数名称 (参数列表);  //此处参数为实际传递的数据(实参)

        PS: 实参会赋值给形参,实参的数量和形参的数量可以不同,如果形参未被赋值则为undefined。

(3)创建带有返回值的函数

//格式:
function 函数名称 (参数列表) {
   函数体
   return 值;
}
 
//调用方式:
函数名称 (参数列表);

         PS:return后的值为返回值,该值是什么,调用函数后的结果就是什么,如果函数中没有return或者return后不加任何值,则返回结果为undefined,return执行后,就会结束函数的执行而且它能直接放到一个表达式的内部。

        return 与 break 的区别:return 用于函数中,结束函数的执行。break 用于循环或者 switch-case,结束循环或者 switch-case 的执行。

3. 递归

        递归是指在函数内部调用自身这个函数,默认是一个死循环。在使用时需要有边界条件,要结合 return 使用。如下,通过一道例题来解释:

//用递归求斐波那契数列第n项的值
function fib(n){
	//边界条件:当n为1或者n为2的时候返回1
	if (n === 1 || n === 2){
		return 1;
	}
	//第n项的值返回 第n-1项 + 第n-2项 的值
	return fib(n-1) + fib(n-2);
}
console.log( fib(6) );//输出值为8

PS:斐波那契数列,第一项和第二项为1,从第三项开始每项的值为前两项之和,如:1,1,2,3,5,8,13,21......

首先创建带有参数 n 的函数 fib,n 代表数列的第 n 项,因为斐波那契数列的前两项为1,所以判断 n 为1或者 n 为2时返回1。除前两项之外,剩余的返回该项的前两项之和即(n-1)项和(n-2)项之和。直接调用 fib(n-1)+fib(n-2) 就是使用了递归的思想,调用函数本身。

函数的递归需要注意一点:JavaScript 的运行特点是单线程,无法充分利用 CP U的内核,深层次的递归嵌套 JS 则会非常缓慢,所以递归并不是在任何情况下都适用。

4. 匿名函数

        匿名函数就是没有函数名称的函数 function ( ){ }

(1)创建匿名函数

var fn = function( ) { }     函数表达式方式(变量名称即函数名称)
function fn( ) { }           函数声明方式

对比匿名函数函数名称( )
        函数名称  本质上就是一个变量,保存了一个函数
        函数名称( );  调用一个函数,执行函数体中的代码,得到函数的返回值

对比函数声明函数表达式
        函数声明存在函数的提升,可以先写调用再写创建
        函数表达式只是提升变量的声明,不提升赋值,必须先写创建再调用

(2)匿名函数的自调用

(function(){

})();

匿名函数自调用的目的是创建一个函数作用域,防止全局污染。全局污染:全局变量访问范围大,对其他变量带来的影响。举例:

(function (){
    var num = 2;
    console.log(num);
})();

函数体中变量num的值为2,进行自调用后打印 num。

(3)回调函数

        将函数以参数的形式传递,传递的这个函数就是回调函数。如下:

//回调函数
function tao(madai){
	console.log('开始第1棒');
	console.log('到达第1棒终点');
	//madai = dong;
	//传递的函数被madai接收
	//调用madai,意味着调用传递的参数
	madai();
}
function dong(){
	console.log('开始第2棒');
	console.log('到达第2棒终点');
}
//此处dong作为参数进行传递,所以dong就是回调函数
tao(dong);
tao(function(){
	console.log('第三棒开始');
});

console.log(typeof tao);//function

二、作用域

        全局作用域:在函数以外的就是全局作用域,声明的变量为全局变量,在任意的作用域下都可以访问到全局变量。

        函数作用域:在函数内的为函数作用域,声明的变量为局部变量,局部变量只能在当前的作用域下访问到。在函数作用域下又有全局函数与局部函数之分,在全局作用域下创建的函数就是全局函数,可以在任意作用域下访问;在局部作用域下创建的函数就是局部函数,只能在当前作用域下访问。

        特别注意在程序执行前,会将 var 声明的变量提升到变量所在作用域的最前面,但只提升声明,不提升赋值,这是变量提升;在程序执行前,会将整个函数提升到所在作用域的最前面,这是函数提升。函数提升优先于变量提升。

如下程序:

//全局作用域
var a = '北京';//全局变量
function s(){
	//函数作用域
	var b = '海淀区';//局部变量
	console.log(a);
	}
	shi();
	console.log(b);
function h(){
	//函数作用域
	var c = '石景山区';//局部变量
	}

        在函数以外的就是全局作用域,所以声明的变量 a 就是全局变量。函数 s 和 h 以内的为函数作用域,所以在它们内部声明的变量 b、c 全部为局部变量。a 为全局变量,即使在函数 s 的作用域下进行打印依然能够成功,因为它是全局变量。而 b 和 c 均为局部变量,只有才函数以内打印才能成功。