闭包
1.定义
有作用域的代码块
2.常见设计
(1)保存临时变量
函数都具有作用域,嵌套的函数可以依次向外层函数寻找自身没有的变量,但当访问到上一级函数变量时,该函数没有被调用而自身无法保存变量的值时,就需要引入一个可以自调用函数来替下一级函数保存变量的值。例子:
注意:
//函数不会保存a的值,因为for循环结束之后代码才开始运行,而a的值早已改变为2,所以函数再运行时所能保存到的a也为2。
// 所以要想要在arr[0](a)执行后打印出0,就需要有自调用fm函数替fn函数保存a的值。
2.封装保护代码块
利用函数的作用域,当变量名被重复使用,而变量为不同含义所赋值也不相同时,就需要函数来将重复变量和要使用该变量的代码块保护起来来实现对应的功能。
3.间接访问函数变量并赋值
一个函数如果在A作用域生成,在B作用域调用,而在执行函数时也会在A作用域中执行。
如果要在一个函数外部访问该函数内部变量并赋值,就需要使用闭包。
例子:
// pay(20)中的20就是赋值给fy函数中的a变量的实参
4.内存泄漏
函数在调用完成时,并且之后将不会再调用并执行函数时,则函数内部的变量等内容将会占用内存,导致内存泄露。
解决方法就是放空不再使用的函数,或者不使用闭包。
回调函数
先运行工具函数,然后把工具函数产生的参数传入到业务函数中进行使用。此时目标函数就是回调函数。 例子:
// 代码运行顺序
// 声明函数tool,ziji
// 运行tool(ziji)
// 此时ziji这个函数将赋值给tool函数小括号里面的形参cb
// 运行tool函数代码
// var a=1;
// a=a+1=2;
// 然后再运行ziji(a)
// 此时就会运行ziji这个函数的代码,并将a这个实参赋值给b这个形参
// 最后完成打印
函数自调用
1.自调用函数
自调用函数也称之为立即执行函数,函数只执行一次,函数执行完毕后自动销毁函数,但是可以将返回值保存。例子:浏览器会报错吗?为什么?
// 浏览器不会报错,但是这个函数也不会运行
2.函数的定义式
当函数定义以后,直接在函数结束的大括号后面加上一个小括号函数就可以自己运行,即自调用函数表达式,也就是自调用。例子:
3.函数的声明
类似于function fn(){}这样的表达式就是函数的声明,必须要调用了函数才会运行函数里面的内容,而要然声明的函数表达式自调用就必须要将函数表达式用小括号括起来,然后再加小括号进行自调用。例子:
4.循环自调用函数
例子:
// 当给函数fn输入实参时,5>3函数在全局域中返回5*fn(4)
// 虽然fn(4)是在fn函数中被调用,但是fn(4)在全局域中生成,所以fn(4)在全局域中返回4*fn(3)
// 同理fn(3)在全局域中返回2
对象的方法
对象中除函数外的成员都被称为对象的属性,而对象中的函数被称为对象的方法。
任何函数运行一定有函数在调用,全局的所有变量和函数都是window。
例子: