一 函数function
函数: 就是一些预先设定好的功能,有的需要我们提供数据,有的不需要
函数分为:系统函数和自定义函数
系统函数不是我们自己写的,比如:Number() parseInt() parseFloat()...
|
1. 创建自定义函数
function 函数名称(){
函数体(调用函数时执行的具体功能)
}
|
1. 函数必须调用才会执行!
2. 调用格式: 函数名称()
3. 函数调用一次就执行一次,调用多次执行多次
|
2. 创建带有参数的函数
function 函数名称(参数列表){ //形参
函数体
}
调用函数的格式:
函数名称(参数列表) //实参
|
形参: 函数定义时,参数列表中的参数,用于接收调用函数时传入的值
实参: 函数调用时,参数列表中的参数,是实际传入的具体数据
1. 实参的值会赋值给形参
2. 实参与形参的个数可以不匹配
如果实参个数小于形参,未被赋值的形参值为undefined
如果实参个数大于形参,多余的实参会被舍弃
|
3. 创建带有返回值的函数
function 函数名称(参数列表){
函数体
return 值 //返回值
}
|
1. return用于向外部返回当前函数执行后的结果
2. 调用带有返回值的函数,我们可以在外部拿到当前函数执行的结果
3. 如果函数中没有写return或者return关键字后没有值,外部拿到的结果是undefined
4. 一旦遇到了return,函数会直接结束(return后不可以写代码,不会执行)
|
4. continue break与return
continue使用在循环中,用于结束本轮循环continue后面的语句,开启下一轮循环
break用在循环中,用于结束当前层循环 break用在switch中,用于防止switch的穿透现象 return用在函数中,用于给函数返回最终结果,也用于直接结束函数
|
二 变量的作用域
全局作用域: 在函数以外的作用域,只有一个全局作用域
函数作用域: 在函数以内的作用域,可能有多个函数作用域
全局变量: 在全局作用域下声明的变量,可以在任意作用域下访问到
局部变量: 在函数作用域下声明的变量,只能在所属的函数作用域下访问到
注意: 我们这里说到的访问指的是 获取 + 修改
|
在函数内,不加var声明的变量是全局变量
注意:这只是一种特殊现象,我们定义全局变量时还是要按照规范来写
|
JS的预加载/预解析:
在程序执行之前,会将用var声明的变量提升到所在作用域的最前面
但注意: 只提升声明部分,赋值部分不提升
|
其他规则:
1. 变量的查找原则: 就近原则,当前作用域下有就不再往全局作用域下查找
2. 形参属于局部变量,只能在函数内访问
|
三 函数的作用域
全局函数:在全局作用域下创建的函数,可以在任意作用域下调用
局部函数:在函数作用域下创建的函数,只能在当前的函数作用域下调用
注意: 局部函数需要在全局函数中调用,才会执行,只调用全局函数,局部函数是不执行的
|
作用域链: 作用域之间嵌套所形成的作用域结构
在查找变量的时候,先在当前作用域下查找,如果没有会沿着作用域链往上一级不断查找
|
函数提升: 程序执行前,会将函数整体提升到所在作用域的最前面
|
<script>
var a = 1
function zoo(){
var a = 2
function zoo2(){
console.log(a)
}
zoo2()
}
zoo() //2
四 匿名函数
思考:
fn fn() 有什么区别
匿名函数: 没有名字的函数
匿名函数的创建方式:函数表达式
var 变量名 = function(){
函数体
}
把匿名函数赋值给一个变量,变量名称就相当于是函数名称
|
对比一下函数名称和函数名称()
函数名称:本质上是一个变量,变量中保存了一个函数类型的值
函数名称():这是在调用函数,执行函数体中的代码
|
对于函数声明和函数表达式的区别:
函数声明:就是我们创建的带名字的普通函数,存在函数的整体提升
函数表达式: 就是我们创建的匿名函数,只存在声明提升!
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>函数提升</title> </head> <body> <script> f1()//因为函数声明创建的普通函数存在整体提升 function f1(){//函数声明 console.log('我是一个带名字的普通函数') } f1()
//f2()//f2 is not a function f2只提升了声明部分,还未赋值,不能当函数用 console.log(f2)//undefined,f2作为变量只存在声明提升 var f2 = function(){//函数表达式 console.log('我是通过函数表达式创建的匿名函数') } f2() //赋值后就可以正常使用了 </script> </body> </html>
|
注意: 函数本身也是一个值,类型typeof是‘function’
这是我们遇到的第6种类型,函数类型属于引用类型,后面阶段学
|
【面试题】 下列程序的执行结果是?
var c = 2 function c(){ console.log(666) } c() //此处的变量c原本保存的函数值被2覆盖,所以报类型错误
|
结论:函数名称与变量名称相同时,函数整体提升后,变量声明就不再提升了 |
五 全局污染与解决方案
全局污染: 全局在不同位置生效了多个同名变量,值会互相影响
全局作用域: html中的script标签下和每一个外部的js文件,都是全局作用域
|
全局污染的解决方案:匿名函数自调用
;(function(){
匿名函数的函数体,在此函数作用域,变量都是局部变量
})()
; 在匿名函数自调用前加分号,结束上一行,就可以防止和上一行代码连接到一起执行
() 前面的小括号把匿名函数整体包裹起来,表示这是一个整体
() 后面的小括号,表示要调用当前这个匿名函数了
|
匿名函数自调用
六 回调函数
函数可以传的值:
fn(77) 函数的实参可以是数值类型
fn(‘hello world’) 函数的实参可以是字符串类型
fn(false) 函数的实参可以是布尔类型
前面我们讲过,函数也是一种类型function,那函数可以作为实参传给别的函数吗?可以
函数的实参可以是函数类型,分为两种:
fn(函数名称) —— 普通函数直接传递函数的名称就可以
fn(匿名函数) —— 匿名函数需要传函数的全部内容
|
回调函数的概念:
回调函数就是把一个函数类型的值作为参数传递,传递的函数就称作回调函数
|
回调函数的格式: function xin(madai){ madai() //调用传递进来的函数的功能 } function ming() { } xin(ming) //普通函数直接传递函数名即可 xin(function(){...}) //匿名函数传递整体内容
|
获取函数执行后的结果,有两种方式:
1. 通过return返回结果
2. 通过回调函数,把值放入到回调函数的参数中带出
|