一.函数的概念
函数就是把一段代码(任意多条语句)封装起来,可以实现某种行为方法,它只定义一次,但可以被执行或调用任意次。
函数的分类
系统函数 window里面的所有函数都属于系统函数 (console.log() alert() prompt()...)
内置函数 所有的内置对象里面的函数 都叫内置函数 (Math.pow())
自定义函数( 自己定义的函数)
二.函数的声明和调用
1.使用function关键词 定义匿名函数(没有名字的函数)
function(形参(可以省略的 可以有多个)){
函数体(代码)
}
//直接调用 让别人(事件)去调用(自动调用)
(function(){
console.log('匿名函数')
})() //()在此为调用此函数
匿名函数用的较少,因为没有复用价值
2.使用function关键词 定义具名函数 (有名字的函数)
function 函数名(形参1,形参2,...){//可以有多个形参,也可以有0个形参
函数体(代码)
}
//声明 具名函数(第一种)
function sayHello(){
console.log('hello')
}
sayHello()//调用函数
//传递参数
function sayHello1(name,age){ //形参是形容的参数
console.log('hello'+name+age)
}
sayHello1('李四') //传进的是实参 根据你要的参数个数来传递对应的参数个数
//调用
// sayHi() //在声明函数前面调用会报错
// console.log(sayHi); undefined
//具名函数的变种声明 (第二种)
var sayHi = function(){
console.log('hi')
}
sayHi()
3.使用new Function方式
var 函数名 = new Function('形参1,形参2','函数体')
//定义
var sayBye = new Function('console.log("bye bye!!")')
//调用
sayBye()
//传参
var sayBye = new Function('username','console.log("bye bye!!"+username)')
//调用
sayBye('李四')
注意: 1, 必须使用function关键字, 且为小写, 函数名可以自己给定 2, 函数名的命名规则和变量名一致 3, 函数名后必须写圆括号()
函数的嵌套
函数的嵌套: 函数内部可以再包含其他函数;
函数之间允许相互调用,也允许向外调用, 但是不可以调用同级函数的嵌套函数;
function fn1(){
console.log('函数1');
function fn2(){
console.log('函数2');
// fn1() 没有结束就是死循环
}
function fn3(){
console.log('函数3');
//调用函数2
fn2()
}
fn2()
fn3()
}
fn1() //函数1 函数2 函数3 函数2
三.参数的声明
函数的参数包括形参和实参
形参:出现在函数定义中,在整个函数体内都可以使用。形参相当于定义在函数内部的变量,是形式上存在的(即声明了没赋值)
实参:出现在主调函数中,实参将值传递给形参。实参是具体的值。
函数不介意传递进来多少参数,也不会因为参数不统一而错误。函数体内可以通过arguments 对象来接收传递进来的参数。
arguments可以判断参数的个数,arguments是个伪数组。 我们可以使用arguments.length来获取参数的个数 可以使用arguments[i] 的方式来访问数组中的第i个参数。
四.函数的返回值
函数都有一条return语句,return语句导致函数停止执行(后面的语句不会再执行),并返回它的表达式的值给调用者。 如果return语句没有相关的表达式,则返回undefined。
五.函数的优点及注意事项
优点:
1, 函数可以在同一个程序或其他程序中多次重复使用(通过函数名调用)
2, 使程序变得更简短而清晰 , 提高可读性
3, 有利于程序维护
注意:声明的函数如果不调用,函数相当于不存在。通过调用找函数。
六.作用域的概念
任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。
在JavaScript中,变量的作用域有全局作用域和局部作用域两种。
全局作用域(变量):整个程序都有效,即整个代码中都可以调用(变量前面没有添加var变成全局的属性)
局部作用域(变量):只对函数内部有效,即只能在本变量声明的函数内部调用。
七.作用域链
通俗地讲,当声明一个函数时,局部作用域一级一级向上包起来,就是作用域链。
在函数体内,局部变量的优先级高于同名的全局变量-作用域链
当执行函数时,总是先从函数内部找寻局部变量如果内部找不到(函数的局部作用域没有),则会向创建函
数的作用域(声明函数的作用域)寻找,依次向上查找。
例:
var a = 20
function fn(){
console.log(a);//undefined 没有var关键词就20
var a = 10
if(10>9){
console.log(a);//undefined 没有var关键词就10
var a = 30
if(5>4){
console.log(a);//undefined 没有var关键词就30
var a = 40
if(a>10){
console.log(a);//40
}
}
}
}
fn()
八.JS的编译和执行
S的解析过程分为两个阶段:预编译期(预处理)与执行期。
第一阶段(预编译期): JS会对本代码块(script)中的所有声明的变量和函数进行处理(类似与C语言的编译),但需要注意的是此时处理函数的只是声明式函数,而且变量也只是进行了声明但未进行初始化以及赋值。
1、先找var和function关键字,如果找到var关键字,提前赋值undefined给变量名. 如果找到function,提前将整个函数赋值给函数名称。
2、如果函数和变量出现重名,函数优先。
3、函数的参数类似于变量,函数内部同样做预解析,支持预解析。
第二阶段(执行期):在编译后的基础上开始从上到下执行脚本,遇到错误时中断。
函数执行过程
1.把对应的开辟的function内存里面的代码块丢给方法栈(执行栈)去执行
2.执行栈就会自动取执行对应的方法 执行完返回对应的结果
3.当前结果返回完毕以后 对应的执行栈里面的内存空间要进行回收(GC)将这个内存空间销毁
九.递归函数
递归可以完成所有循环做的事情 (但是递归的效率较低)
递归三要素
找规律
找临界值(没有规律的值)return
自己调自己(在函数内部调用自己的函数)
例:
// 1 2 3 5 8 13 21 第100位值(递归的效率极低 一般不使用递归 不推荐 (文件的遍历 菜单遍历 深
拷贝))
function fn2(n){
if(n==1){
return 1
}else if(n==2){
return 2
}else{
return fn2(n-2)+fn2(n-1)
}
}
console.log(fn2(7));
十.Dom的简单操作
1.获取对应的标签 (通过id获取)
2.input框的值获取 value属性
document.getElementById('id的属性值')
document.getElementById('input框的id').value //得到input框内的值
3.点击事件 onclick
例(以事件做为驱动)
element.onclick = function(){
//相关操作
}
//通过输入框输入数值判断对应的奇偶并打印
<input id="number" type="text">
<button id="btn">判断奇偶</button>
<script>
function handlerClick(){
//拿到input框里面的内容 获取到input框
var inputValue = document.getElementById('number').value //string类型
// console.log(typeof inputValue); 如果是+法操作必须要先转类型
//判断奇偶的操作
if(inputValue%2==0){
console.log('当前为偶数');
}else{
console.log('当前为奇数');
}
}
//首先需要点击按钮 获取按键 加点击事件
//事件触发自动调用对应的函数 (事件驱动)
document.getElementById('btn').onclick = handlerClick
</script>
例 :简易计算器
html代码:
<input type="text" class="num1">
<select name="" id="s">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" class="num2">
=
<input type="text" class="r">
<button class="btn">计算</button>
js代码:
//定义一个计算值的函数
function fn(num1,num2,operator1){
switch(operator1){
case '+': return num1+num2
case '-': return num1-num2
case '*': return num1*num2
case '/': return num1/num2
default: console.log('参数错误');
}
}
var num1 =document.querySelector('.num1')//通过类名然后.value获得第一个数的输入框的值
var num2 =document.querySelector('.num2')//通过类名然后.value获得第二个数的输入框的值
var s =document.querySelector('#s') //获得操作符
var r =document.querySelector('.r') //结果框,计算完后赋值给它
var btn = document.querySelector('.btn') //按钮,点击计算
btn.onclick = function(){ //点击后执行函数计算
r.value = fn(Number(num1.value),Number(num2.value),s.value)//调用fn函数计算出结果后赋值
}