导图社区 JavaScript函数
这是一篇关于JavaScript函数的思维导图,主要内容包括:回调函数,1.arguments实参数组,立即执行函数,闭包函数(超级重点),十、变量作用域,九、递归函数,八、返回值(重点),七、函数的重载,六、形参和实参,五、函数中的参数,四、函数调用,三、函数的其他声明方式(函数表达式),二、函数的作用,一、函数的定义。
编辑于2024-09-30 10:32:01这是一篇关于JavaScript函数的思维导图,主要内容包括:回调函数,1.arguments实参数组,立即执行函数,闭包函数(超级重点),十、变量作用域,九、递归函数,八、返回值(重点),七、函数的重载,六、形参和实参,五、函数中的参数,四、函数调用,三、函数的其他声明方式(函数表达式),二、函数的作用,一、函数的定义。
这是一篇关于面向对象编程的思维导图,主要内容包括:改变this指向,this指针变量,构造函数里面的this,对象的继承,构造函数与特殊属性结合,特殊需求属性,构造函数与普通函数的区别,使用构造函数创建对象(超级重点!!!),对象的定义。
这是一篇关于JavaScript的思维导图,主要内容包括:数据类型检测,JavaScript的弱类型机制,学习前的注意事项,JavaScript数据类型,BOM:Boswer Object Model 浏览器对象模型,DOM:Document Object Model 文档对象模型,ECMAScript :JavaScript的语法。
社区模板帮助中心,点此进入>>
这是一篇关于JavaScript函数的思维导图,主要内容包括:回调函数,1.arguments实参数组,立即执行函数,闭包函数(超级重点),十、变量作用域,九、递归函数,八、返回值(重点),七、函数的重载,六、形参和实参,五、函数中的参数,四、函数调用,三、函数的其他声明方式(函数表达式),二、函数的作用,一、函数的定义。
这是一篇关于面向对象编程的思维导图,主要内容包括:改变this指向,this指针变量,构造函数里面的this,对象的继承,构造函数与特殊属性结合,特殊需求属性,构造函数与普通函数的区别,使用构造函数创建对象(超级重点!!!),对象的定义。
这是一篇关于JavaScript的思维导图,主要内容包括:数据类型检测,JavaScript的弱类型机制,学习前的注意事项,JavaScript数据类型,BOM:Boswer Object Model 浏览器对象模型,DOM:Document Object Model 文档对象模型,ECMAScript :JavaScript的语法。
JavaScript函数
一、函数的定义
函数的定义方式非常多,目前我们只看一种标准方式,语法如下:function 函数名(参数, ...){ 函数体 }
注意点
1.关于函数名,参照变量取名规范
2.函数体,函数的代码体,里面可以是任意的多条语句
3.后面的大括号不能省,声明一个函数出来就必须要有函数体
二、函数的作用
三、函数的其他声明方式(函数表达式)
语法:var 函数名 = function(){ }
具体:var sayHello = function(){ console.log("hello") }
注意: 上面两种声明方式看似一样,实际有区别 abc(); function abc(){ console.log("hello abc"); } def(); var def = function(){ console.log("hello def"); } 通过第一种方式声明的函数,可以在定义之前调用,而通过var定义的函数在定义之前调用会报错
四、函数调用
函数定义好之后,不会自己执行,他需要经过调用才会被执行,函数的调用通过函数名来完成,语法如下:函数名()
注意: 函数的实际调用过程中,我们需要注意,函数名与后面的小括号实际上分别指 的是两个操作
function abc(){ console.log("hello abc"); } abc() //调出代码体中所包含的代码,并执行 abc //调出函数,但是不执行 代码分析: 如果只写函数名不写后面的小括号,我们会发现,函数体内的代码并没有被执行,也没有报错,因为在后面并没有写小括号,我们可以把小括号理解成是一个函数的立即执行符,前面的函数名负责调出函数,后面的小括号负责执行函数 也就是说,我们可以把调用函数的语法理解成是由两个部分组成,分别是调(函数名)和用(小括号)两个部分来看
五、函数中的参数
现在有如下情况: var username; function sayHello(){ console.log("大家好,我叫" + username); } username = "张三"; sayHello(); username = "李四"; sayHello(); username = "王五"; sayHello();
当我们调用sayHello的时候,我们可以根据变量username去动态改变打印的结果,这个username是定义在函数体外的,如果定义在函数体,我们无法多次赋值,同时定义在函数体外的变量我们叫全局量,全局变量可以在任意函数中调用,但是声明在函数体内的变量叫做局部变量,局部变量无法实现跨域调用
这个时候,我们可以引入参数让函数变的更灵活function sayHello(username){ console.log("大家好,我叫" + username); } sayHello("张三"); sayHello("李四"); sayHello("王五"); 有了参数的引入,函数的作用的灵活性会有很大的提升
六、形参和实参
形参:形式参数,指的就是在函数声明的时候小括号里面写的参数名
实参:实际参数,调用函数的时候,小括号里面写的值
function add(a,b){ console.log(a + b); } //上面的函数中,a和b就是形参,没有具体的值,也没有具体的类型 add(4,5) //在调用的时候,给a和b赋值了实参,现在的4和5就是a和b的实参 也可以是如下情况: var x = 5; var y = 6; function add(a,b){ console.log(a + b); } add(x,y); 这个时候,x和y就是add函数的实参,因为x,y中是有实际的值,通过这个add的调用,实参x赋值给了a,实参y赋值给b
七、函数的重载
函数的重载指的是在定义的时候,它的函数名相同,而函数的参数个数不同,参数的数据类型不同,这个时候,同名的函数就叫做函数的重载(overload)
JavaScript中函数不存在重载,只有强类型的语言才有重载
function add(a,b){ console.log(a,b) } function add(a,b,c){ console.log(a,b,c) } 这个时候我们看到函数名相同,但是函数的参数个数不同,我们的重载是根据参数的个数和参数的类型来决定的,但是,在JavaScript中,这两点都无法实现
(1)JS是弱类型语言,变量在没有赋值之前都undefined,所以,不能通过类型区别 (2)JS的函数中的形参和实参没有必要形参一一对应的关系,这个也无法通过参数的个数去区别
JS当中不存在重载,当出现同名的时候,会发生覆盖
八、返回值(重点)
函数的返回值是指函数将内部某些值返回到函数体外的一个操作,使用一个叫做return的关键字,JS中每个函数都可以有自己的返回值
举例: function abc(){ return "hello"; } var x = abc(); 这个时候,abc函数会返回一个“hello”,然后变量x接收这个abc函数的返回值,所以x的值就是“hello” function add(a,b){ var c = a + b; return c; } var y = add(10,20); 这个时候变量y接收add函数的返回值,结果为30 注意:函数其实有默认的返回值,undefined
return打断函数执行
return可以把函数内的值返回到函数外使用,同时,一个函数碰到了return就会跳出当前函数的执行,return后面的代码不再执行function def(){ var a = 10 + 20; return; console.log(a); } return可以打断函数的执行,所以后面的console.log(a)无法被执行
如果不需要返回值,但是依然使用了return,这个时候return就是一个单纯的打断操作 如果有返回值,那么return把值返回到函数外同时打断函数执行
九、递归函数
如果一个函数在内部又调用了自己,那么这个函数我们就叫做递归函数递归函数可以通过循环来演示,所以我们先看一个循环 //我们要求1-10之间整数的和 var a = 0; for(var i = 1;i <= 10;i++){ a += i; } console.log(a);
如果我们需要把上面的循环转换程递归来表示,首先需要先弄情况三个东西,初始值,循环条件,自变量var a = 0; var i = 1; function add(){ a += i; // a = a + i; 1:1 i++; // i:2 if(i <= 10){ add(); // a = a + i; 2:3 //3 } }
十、变量作用域
我们之前学习的时候同var关键字声明变量,这个var定义的变量是没有块级作用域的 var a = 123; //全局变量 if(true){ console.log(a); } //-------------------------------- { var b = 123; } console.log(b); //-------------------------------- for(var i = 1;i <= 10;i++){ var c = "haha" } console.log(c);
这个变量从效果上来看其实都可以看做全局变量,这里的大括号并没有形成块级作用域,这一点与其他编程语言不太一样,但是注意一点,function的大括号会形成作用域 function abc(){ var a = 1; //这里a是一个局部变量,只能在大括号以内调用,出了大括号就不能用 } console.log(a); //报错,a找不到
回调函数
回调函数就使把一个函数作为另外一个函数的实参传入,被当作实参传入的函数我们就叫做回调函数
1、当某些功能需要分段执行的时候(流水线操作)
2、当一个函数的返回值无法返回的时候 function abc(x,y,z){ var a = x + y + z; var b = x - y - z; return [a,b]; //如果我们需要把上面的a和b同时返回出去,目前看来只能通过数组的方式 } 现在的问题:能不能不使用数组,我们通过回调来完成function abc(x,y,z,callBack){ var a = x + y + z; var b = x - y - z; //return [a,b]; //如果我们需要把上面的a和b同时返回出去,目前看来只能通过数组的方式 callBack(a,b); } function print(_a,_b){ console.log("三个数的和" + _a); console.log("三个数的差" + _b); } abc(10,20,30,print)
小练习: 小明和张三,它们都在吃东西,我们想让小明吃面和可乐,让张三吃饭和白开水 function food(callBack){ var noodle = "面"; var coc = "可乐"; var rice = "饭"; var water = "水"; callBack(noodle,coc,rice,water); } function eat(_noodle,_coc,_rice,_water){ console.log("小明在吃" + _noodle + "喝" + _coc); console.log("张三在吃" + _rice + "喝" + _water); } food(eat);
闭包函数(超级重点)
1.JS垃圾回收机制
声明在函数体内的变量会在函数执行完毕之后瞬间销毁闭包例子: function f(x){ var a = x; //局部变量 a = 5; var b = function(){ //声明函数b return a; //在函数b内部调用a } a++; //递增运算 a = 6; return b; //返回函数b的函数体 } var c = f(5); //function b(){return 6} 代码分析: 声明在函数体内的变量是局部变量,局部变量只能在函数体内声明并调用,现在我们在外层函数f中声明一个局部变量a,又声明了一个函数b,并且在其内部调用了外部函数的局部变量a,现在会形成一个闭包表现
总结下来,如果要形成闭包: 在内部函数里面return外部函数的局部变量,在外层函数里面return内层函数的函数体
2.闭包的作用
闭包函数其实就是为了让内部函数调用外部函数的变量,然后让外部函数讲内部函数的函数体返回出去,从而达到可以调用局部变量的目的
这样做的意义是什么? 我们为什么不要声明在外层函数的局部变量直接拿到外面作为一个全局变量来声明使用
为了数据安全性 首先我们先明确一点,变量是用来储存数据的,同时由于作用域的给厝,变量又分成了全局和局部两种,作为全局变量来说,在程序运行的时候任何人在任何时候都可以进行访问的,那么对于存在全局变量中的数据的安全性就会有一定影响,而局部变量作为声明在函数体内的变量,自身有一个特性,当函数执行完毕之后会立即释放掉,同时又因为作用域的关系,局部变量是无法被外部直接访问的,那么,我们就认为局部变量相比全局变量对于数据的安全性会更好,但是又由于在函数调用结束之后会立即释放掉,所以导致局部变量无法长时间做为临时存储来使用
现在我们即需要局部变量的相对的安全保障,同时又需要局部变量不能在函数执行结果之后被垃圾回收机制回收掉,所以就出现了闭包函数的调用形式,这种形式下的函数执行完毕之后,其内部的局部变量不会被回收
3.使用闭包的注意事项
闭包虽然可以解决一些问题,但是也会带来一些问题,由于闭包会携带外部函数的局部变量,所内存占用是比较大的,所以,尽量少用,慎用闭包
函数内部的局部变量不会被垃圾回收销毁,增大内存消耗,导致内存泄漏,解决方案就是可以使用完之后手动给变量赋值null,或者通过delete关键字手动删除
因为闭包的使用可以使内存中一致维持一个局部变量的存在,可以作用缓存,也可以相对的提高数据安全性
4.闭包立即执行
(function a(){ var username = "zhangsan"; console.log(username) })(); 注意:这里其实就使一个立即执行函数,只不过没有采用 !或+的方式来进行
立即执行函数
1.arguments实参数组
我们讲过形参和实参没有必要形成一一对应的关系,形参不介意你多传及格实参,也不在乎你传递的实参是什么类型,也就是说,如果我们定义两个形参,但是调用的适合可以传递一个实参,三个实参都是没有问题function abc(a,b){ console.log(a); console.log(arguments[2]); console.log(arguments[0]); } abc(1,2,5);
(1) arguments解析
这个arguments是一个类数组的概念function abc(a,b){ console.log(Array.isArray(arguments)); //false } 解析: 通过isArray方法判断得到一个结果arguments不是一个数组,但是它又可以使用数组的语法
(2) 数组与类数组的区别
1.数组Array会有自己的方法,而arguments是没有的
2.它们都有length属性和索引,而索引和length属性是数组才有的特性
总结:在JavaScript中,当一个对象具备数组的特征(索引和length),但是不具备数组的方法,这种对象我们叫做类数组
注意:arguments只能在函数体内使用,每一个函数都有自己的arguments,出了函数就没用了
9-24