函数
制作简易计算器
<input type="text" id="txt1">
<!-- 注意点:option标记的value可以直接通过select的value直接获取,当你选中是那个option,获取到的就是那个option的值 -->
<select id="sel">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" id="txt2">
<button id="btn">=</button>
<input type="text" id="txt3">
<button id="clear">clear</button>
<script>
// 封装选择器
function $(id){
return document.getElementById(id)
}
// 获取元素
var txt1 = $('txt1')
var txt2 = $('txt2')
var txt3 = $('txt3')
var sel = $('sel')
var btn = $('btn')
var clear = $('clear')
// 绑定事件
btn.onclick = function(){
// 非空验证
if(txt1.value == '' || txt2.value == ''){
alert('亲,内容不能为空?')
return
}
var num1 = Number(txt1.value)
var num2 = Number(txt2.value)
// 根据输入符号进行匹配
switch(sel.value){
case '+':
txt3.value = num1 + num2
break
case '-':
txt3.value = num1 - num2
break
case '*':
txt3.value = num1 * num2
break
case '/':
txt3.value = num1 / num2
break
}
}
// 清空文本框的值
clear.onclick = function(){
txt1.value = ''
txt2.value = ''
txt3.value = ''
}
</script>
作用域
指的是访问数据时的规则(区域、范围)
分类
- 全局作用域,整个script标记内部都属于全局作用域
- 局部作用域,指的是函数内部
变量分类
- 全局变量,声明全局作用域里面的变量,称之为全局变量(声明在函数外部)
- 局部变量,声明在函数内部的变量,称之为局部变量
访问数据规则
- 外部不能访问函数内部的变量
- 函数内部可以访问函数外部的变量
注意:在函数内部声明的变量,如果没有使用var关键字的话那么它就属于全局变量
js设计缺陷
- 要求声明变量时必须使用var关键字,但是在实际的使用过程中你不使用其实变量也可以声明
function fn(){
// 要求在函数内部声明的变量属于局部作用域,结果呢?就是由于没有使用var关键字,既然在函数外部可以使用
b = 30
}
fn()
console.log(b)
- 在函数内部不使用var,局部变量会变成全局变量
- 关于name问题:name不是关键字,但是你使用后,会出现一些其他的情况
问题1:使用name声明变量,注释后去打印结果依旧存在
var name = '张三'
console.log(name)
var a = '张三'
console.log(a)
问题2:当你使用name给它赋值为引用数据类型时,不会按照数据类型规则去解析(因为你给name赋值的所有数据类型它都会转成字符串类型)
var name = function(){
onsole.log('你好!')
}
console.log(name)
name() // name is not a function
var name = 10
console.log(window)
作用域链
- 作用域链把作用域详细进行了划分,把全局作用域称之为0级作用
- 把函数内部划分为1级、2级、3级等等作用域(函数嵌套函数的情况下,以函数的嵌套关系划分)
- 把这些作用域连接起来形成一个类似于链条的关系,把这种情况称之为作用域
访问规则:
- 先在当前的作用域里面进行查找
- 如果找到就使用,如果没有找到就去上一级作用域里面进行查找,直到找到0级还是没有就报错了
变量的生命周期
指的是变量从声明到销毁的过程
全局变量: 当网页关闭后才销毁
局部变量: 当函数执行完毕就销毁
预解析
浏览器不会直接按照你写代码的顺序直接去解析代码,需要先把代码加工处理后再去逐行解析代码,把这个加工处理代码的过程称之为预解析
步骤:
- 先把变量声明和函数声明提升到当前作用域的最顶端
- 再根据原先代码的书写顺序逐行执行代码
注意:
- 变量声明指的是 var 变量名称
- 函数声明指的是整个函数体,不包括函数调用
function fn(){}
函数两种声明方式
1.直接声明
function fn(){
console.log('hello')
}
fn()
2.表达式声明
var fn = function(){
console.log('hello')
}
如果把函数赋值给一个变量,那么函数不会进行变量声明提升
fn() // fn is not a function
var fn = function(){
console.log(123)
}
递归函数
- 递归指的是函数自己调用
- 要求递归必须有出口:如果没有结束条件,那么就变成了一个死循环
- 注意点递归是比较好用的,但是得发现规律才行
var i = 0
function buddhistMonk(){
i++
console.log(i+'老和尚讲故事,从前有座山,山里有座庙,庙里有个老和尚,老和尚对小和尚说,从前有座山,山里有座庙,庙里有个老和尚...')
if(i<100){
buddhistMonk()
}
}
buddhistMonk()
递归练习
- 1+2+3+....+100的和?
function getSum(n){
// 第一次进来 5==1 不满足条件,执行下面的代码
// 第二次进来 4==1 不满足条件,执行下面的代码
// 第三次进来 3==1 不满足条件,执行下面的代码
// 第四次进来 2==1 不满足条件,执行下面的代码
// 第五次进来 1==1 满足条件,进入判断体里面,把1直接返回
if(n==1){
return 1
}
/*
5 + getSum(4) 把这个返回给外界
5 + 4 + getSum(3) 把这个返回给外界
5 + 4 + 3 + getSum(2) 把这个返回给外界
5 + 4 + 3 + 2 + getSum(1) 把这个返回给外界
*/
return n + getSum(n-1)
}
// 第一次接收到的结果 5 + getSum(4) 把之前返回的结果保存在内存里面的
// 第二次接收到的结果 5 + 4 + getSum(3) 把之前返回的结果保存在内存里面的
// 第三次接收到的结果 5 + 4 + 3 + getSum(2) 把之前返回的结果保存在内存里面的
// 第四次接收到的结果 5 + 4 + 3 + 2 + getSum(1) 把之前返回的结果保存在内存里面的
// 第五次接收到的结果 5 + 4 + 3 + 2 + 1 = 15
getSum(5)
- 斐波那契数列:1、1、2、3、5、8、13、21、34……
规律:这个数列从第3项开始,每一项都等于前两项之和
分析:fb(n) = fb(n-1) + fb(n-2)
function fb(n){
if(n==1 || n==2){
return 1
}
return fb(n-1) + fb(n-2)
}
fb(5)
array数组
就是一组数据的集合,说明数组里面可以存储很多的数据
声明方式:
[]字面量方式
var arr = ['张三', '王成']
console.log(arr)
new Array()构造函数方式,是创建对象的一种方法(构造函数也是函数,只不过它的功能更为强大,可以直接创建对象)
var arr = new Array('张三', '王成', '王成女朋友')
console.log(arr.length)
注意: 构造函数方式创建的数组,如果给里面传递一个(只有一个数组元素)数值类型的数据,那么它会表示限定数组长度为多少
var arr = new Array(10)
console.log(arr)
数组下标 :
- 名称:下标、索引(index)
- 在创建数组的时候,默认会给每一个数组成员(元素)添加一个编号,用于区分不同的数组元素,把这个编号称之为下标
- 数组的下标默认是从0开始的
- 数组下标作用:可以用来获取数组元素、删除、增加、替换等等
var arrAge = [18, 20, 24, 19, 23]
console.log(arrAge[0])
console.log(arrAge[1])
数组属性:length 表示数组长度
// 遍历数组
for(var i=0; i<arrAge.length; i++){
console.log(arrAge[i])
}
伪(类)数组(arguments对象)
不是真正的数组,但是可以使用数组的属性和方法,把这种数组称之为伪数组
arguments对象
作用:
- 用来保存实参里面的数据
- 当实参或者形参的个数不确定的情况下使用
arguments.length 表示实参的个数
arguments.callee.length 表示形参的个数
arguments.callee() 表示的是当前函数的名称
function getSum(){
var sum = 0
for(var i=0; i<arguments.length; i++){
sum += arguments[i]
}
return sum
}
var res = getSum(10, 20, 30, 60, 80)
console.log(res)
function fn(a, b, c){
// console.log(arguments.callee.length)
// console.log(arguments.length)
if(arguments.length > 3){
alert('亲,实参只能传递三个哦!')
}
}
fn(10, 20, 30)