JS函数
浏览器内置了很多函数,比如alert()
,全称是window.alert()
还有DOM(文档对象模型)的很多方法等等
自定义函数
1 | function funName(p1,p2){ |
注意调用方式,如果将按钮和函数绑在一起,()
是否书写效果是不一样的,()
是函数调用运算符,匿名函数就相当与不写()
的情况
1 | button.onclick = funName();/*这代表不需要点击就调用*/ |
匿名函数
1 | function (){ |
匿名函数一般与事件联系在一起
1 | var myButton = document.querySelector('button'); |
名字空间
为了避免不同文件的变量和函数名重复,可以将所有变量和函数绑定在一个全局变量里,如
1 | let GLOBAL = {}; |
高阶函数
高阶函数英文叫Higher-order function。那么什么是高阶函数?
JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
map
可以快速的将数组的每个元素按照规则得到另一组数组
例如[1,2,3]得到[1,4,9],常规思想是取出元素,进行运算,赋值给其他数组
1 | function mutiple(x){ |
使用map
1 | function mutiple(x){ |
传入的mutiple就是函数本身,因为map将算法抽象了,所以很简洁,而且一眼就看出了新增了一个数组
第二个参数可选,代表索引
reduce
map做的是简单运算,reduce做的是重复运算,传入reduce的函数必须有两个参数,一个作为算子计算,一个接收结果,简单算法如下
1 | [x1, x2, x3, x4].reduce(f) == f(f(f(x1, x2), x3), x4) |
比如对一个数组求和
1 | let arr = [1,2,3,4,5,6,7,8,9]; |
filter
可以过滤掉数组的元素,回调函数的第一个参数是元素(必选),第二个参数是元素索引,第三个参数是数组本身,回调函数应返回一个boolean值来决定是否过滤
如过滤掉一个数组重复的元素
1 | var arr = [1,2,3,4,1,2,3,4]; |
sort
可以对数组进行排序,如果数组里是字符串,会按照首字母的ASCII码进行排序,首字母相同会按照第二个字母的ASCII码排序,以此类推
1 | let arr = ['a','A','Abc','abc'] |
如果是数组,sort默认的方法是将数字转化为字符串,然后使用ASCII码的方式进行排序,如
1 | let arr = [12,22,2,15]; |
但因为sort是高阶函数,它的回调函数接收两个值a、b
- 若a<b,则返回一个负值表示a排在b之前
- 若a=b,则返回0
- a>b,返回一个大于0的数代表a排在后面
1 | // 升序 |
every
测试每个元素是否满足条件
回调函数需要一个参数,会把所有元素传递给函数,会根据函数的返回结果返回布尔值
forEach
会把所有元素传入回调函数,但不会返回任何值,经常用来遍历
find
查找符合规则(自己写函数定义规则)的元素,返回该元素
findIndex
返回索引
闭包
除了将函数作为参数传入以外,还可以将函数返回,而闭包就是将返回一个变量环境的函数,也就是一个有状态的环境,如
1 | function wrapper(a,b){ |
注意使用sum1()
时返回的函数才被调用,sum使用了外部函数的变量,返回的函数将参数保存了起来
因为返回的函数没有被立即执行,所以需要注意的一点就是返回的函数不能使用循环的变量,或则后续会变化的变量,如
1 | function count() { |
为什么会返回16呢,因为函数返回时,i
已经变成了4
如果非要使用,就必须再创建一个函数将变量值存下来
1 | function count() { |
使用了一个‘创建就执行的匿名函数的语法’
1 | (function (x) { |
不加括号会报语法错误
使用场景
模拟私有变量方法
面向对象编程的语言里都可以在对象内封装一个私有变量,例如Java的private,而JS并没有这种机制,但使用闭包就可以封装一个私有变量或者方法
1 | var makeCounter = function () { |
箭头函数
是ES6新增的一个函数定义方式,箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this
,arguments
,super
或new.target
。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
如果函数只是一个表达式,那他的定义非常简单
1 | x => x * x; |
如果有语句
1 | x => { |
如果有多个参数或者无参数
1 | // 两个参数: |
如果要返回一个对象
1 | x => ({foo:x}) |
this
针对前面说的this对象问题在函数的函数里面的指向问题,使用箭头函数就可以解决
1 | var obj = { |
另外,箭头函数的call()
和apply
的第一个参数总是被忽略,他总是与外部调用者绑定
1 | var obj = { |
箭头函数不能使用new,没有prototype,不能作为生成器
generator
生成器(generator)是ES6引入的数据类型,类似函数,但会返回多个值
函数碰到return就会返回值并结束这个函数,如果没有返回值就隐式的代表return undefined
而generator就是可以使用yield
返回多次,比如利用它写一个计数器
1 | function* counter(){ |
实际上也是一个带状态的值,如果在里面写return,执行到return时done就变成true,这个生成器也就结束了