1.函数的分类
普通函数 function 函数名(){普通函数} 事件处理函数 标签.事件类型 = function(){事件处理函数} 表达式函数 var 变量名 = function(){表达式函数} 表达式函数和普通函数有什么区别 表达式函数不能提前调用 普通函数可以提前调用
2.回调函数/callback
概念:将函数作为参数传递给其他函数进行调用的函数
回调函数的使用:一般都是在某个动作或者某个行为完成之后调用
script> /* 回调函数:将函数作为参数传递给其他函数进行调用的函数 回调函数的使用:一般都是在某个动作或者某个行为完成之后调用 */ // 1.定时器 // setInterval(function(){},2000) // setTimeout(function(){},2000) // 2.请求数据 也是模块化操作 function getData(a) { //a= function () { console.log("显示数据")} console.log("开始请求数据") for (var i = 0; i < 10; i++) { console.log("...........") } console.log("结束请求数据") // 显示页面 a() } function showData() { console.log("显示数据") } console.log(showData) getData(showData) /* 必须等这个动作执行完之后 再执行另一个动作 */ </script>
3.匿名函数/立即执行函数IIFE
匿名函数
概念:没有名字的函数
function(){匿名函数}
1.匿名函数 没有名字的函数 function(){ console.log("匿名函数") }
立即执行函数(IIFE)
-
概念:匿名函数的执行也叫立即执行函数
-
语法:(函数声明-匿名函数的声明方式)(调用)
//2.匿名函数的执行也叫立即执行函数(IIFE) //立即执行函数的语法 (函数声明)(调用) (function(){ console.log("立即执行") })()
-
立即执行函数-传参
// 3.立即执行函数---传参 (function(a,b){ //定义形参 console.log("立即执行") console.log(a,b) })(10,20)//实参 传递参数
-
立即执行函数-返回值
// 4.立即执行函数----返回值 var a = (function(a,b){ //定义形参 console.log("立即执行") console.log(a,b) return a+b })(10,20)//实参 传递参数
-
立即执行函数的好处
好处:避免全局污染(声明了大量的全局变量,可以随意访问和修改) 节省内存
console.log(a); /* 好处:避免全局污染(声明了大量的全局变量,可以随意访问和修改) 节省内存 */ var b = 10;//全局变量 可以在任何地方修改和访问,关闭页面的时候才会销毁 (function(){ var c = 30; })()
-
立即执行函数的使用场景
新建ujiuye.js文件
var ujiuye = (function () { function getStyle() { //局部函数 return "我是getStyle函数" } function bind() {//局部函数 return "我是bind函数" } // 使用return返回值 [],{} return { "getStyle":getStyle, "bind":bind } })()
在页面使用
script 引入js文件 ujiuye.getStyle()
4.==闭包函数(Closure )==
-
概念:能够访问其他函数内部的变量的函数 函数套函数
function fun1() { var a = 10; console.log(a++);//10 } fun1(); // console.log(a);//a是局部变量 在外部访问是访问不到的 // 2.闭包函数--普通的闭包函数 function outer() { var a = 10; function inner() { console.log(a++);//10 作用链:先找自身区域的,如果没有,往父级作用域去查找 } inner(); } outer();//10 outer();//10 outer();//10
-
特点:会延伸变量的使用范围,会向全局变量那种一直存在全局变量中,避免全局污染
// 3.经典的闭包 // 特点:会延伸变量的使用范围,会向全局变量那种一直存在全局变量中,避免全局污染 function outer1() { var a = 10; return function () { console.log(a++) } } var inner = outer1(); //inner = function(){consle.log(a++)} inner();//10 inner();//11 inner();//12
-
缺点:大量使用闭包的时候 可能造成内存泄漏 如果不用的时候就释放
// 4.缺点:大量使用闭包的时候 可能造成内存泄漏 如果不用的时候就释放 inner = null; inner();//报错
-
闭包的使用场景<script>
// 1.检测是否使用了闭包 function outer() { var a = 10; function inner() { console.log(a++) } inner() } outer();//10 outer();//10 // 2.多个闭包没有关联 function outer1() { var a = 10; return function () { console.log(a++) } } var inner1 = outer1(); inner1();//10 inner1();//11 inner1();//12 var inner2 = outer1(); inner2();//10 inner2();//11 inner2();//12 // 3.面试题 代码执行的结果是? var arr = []; for (var i = 0; i < 10; i++) { arr.push(function () { console.log(i); }) } // i 最后一次的值 是10 // arr [function,function,function,function,function,function,function,function,function,function] arr[5]();//执行结果 10 // 4.修改代码 如果是arr[5]() 输出5 var arr1 = []; // for (var i = 0; i < 10; i++) { // // console.log(i) // function add(a) {//a = 0 1 // arr1.push(function () { // console.log(a); // }) // } // add(i);//传实参 // } for (var i = 0; i < 10; i++) { (function (a) { arr1.push(function () { console.log(a); }) })(i) } /* 经过for循环代码之后 arr1中存储的内容 arr1 = [ function(){console.log(0)}, function(){console.log(1)}, function(){console.log(2)}, function(){console.log(3)}, function(){console.log(4)}, function(){console.log(5)}, function(){console.log(6)}, function(){console.log(7)}, function(){console.log(8)}, function(){console.log(9)}, ] */ arr1[5]();//5 </script>
-
练习-点击li输出对应的下标
// 5.点击li 输出对应的下标 var lis = document.querySelectorAll("li"); for (var i = 0; i < lis.length; i++) { (function (a) { lis[a].onclick = function () { console.log(a);// 0 1 2 3 } })(i) }