■教学目标
能够说出预解析的概念(其实就是告诉你js语法执行流程
能够说出作用域的概念(js变量哪里可以用
能够说出作用域链的概念&特性(主要特性
■函数(下)
一、预解析(script执行过程)
明确需求
说明:上一讲发现发现定义函数有两种方式,声明式(随意调用)和赋值式(必须后调用)
// 声明式
fn1();
function fn1() {
console.log('hello,webopenfather')
}
fn1();
fn1();
// 赋值式
// fn2();
var fn2 = function() {
console.log('hello,webopenfather2')
};
fn2();
思考:为什么声明式可以先调用,赋值式不行
回答:和js底层代码的执行流程相关(专业术语叫预解析
执行流程
- 预解析( JS代码执行流程
- 规则:
1 读取第一个script标签
2 编译(检查语法、声明变量、声明函数、代码优化等
3 执行
以此类推...
- 举例: var i = 2;console.log(i);
1 读取第一个script标签
2 编译(检查语法、声明变量、声明函数、代码优化等
var i
3 执行
i = 2
console.log(i);
练习:验证执行流程
- a. 执行流程验证1
console.log(num) // ???? num未定义
/*
1 读取第一个script标签
2 编译(检查语法、声明变量、声明函数、代码优化等
3 执行
console.log(num)
*/
- b. 执行流程验证2
console.log(num) // ??? undefined
var num = 2;
console.log(num) // 2
/*
1 读取第一个script标签
2 编译(检查语法、声明变量、声明函数、代码优化等
var num
3 执行
console.log(num)
num = 2;
console.log(num)
*/
- c.分析声明式函数和赋值式函数JS执行过程
//需求:定义声明式函数 fn1
fn1()
function fn1() {
}
fn1()
// --------------------
// 1. 读取script
// 2. 编译(检查语法、声明变量、声明函数、代码优化....
function fn1() {
}
// 3. 执行
fn1()
fn1()
// --------------------
// 需求:定义赋值式函数 fn2
fn2()
var fn2 = function() { //赋值式其实就是变量声明语法 只不过值是一个函数
}
fn2()
// --------------------
// 1. 读取script
// 2. 编译(检查语法、声明变量、声明函数、代码优化....
var fn2
// 3. 执行
fn2() // fn2 它 undefined
fn2 = function() { //赋值式其实就是变量声明语法 只不过值是一个函数
}
fn2()
// --------------------
- d. 声明式函数
先调用后声明
必须写在同一个script标签里面
<script>
console.log(fn) // 直接报错
/*
1. 读script
2. 编译
3. 执行
console.log(fn)
*/
</script>
<script>
function fn() {
}
</script>
练习
fn() // 打印 我是 fn 函数
console.log(num) // 结果? undefined
function fn() {
console.log('我是 fn 函数')
}
var num = 100
/*
编译
function fn() {
console.log('我是 fn 函数')
}
var num
执行
fn()
console.log(num)
num = 100
*/
小总结
预解析是什么:js执行流程
预解析执行流程:
1. 读取第一个script
2. 编译(语法检查、声明变量、声明函数、代码优化等等
3. 执行
二、作用域!!!
明确需求
思考1:下述代码执行结果
var num = 1;
function fn() {
var num2 = 2;
console.log(num) // 1
console.log(num2) // 2
}
fn();
console.log(num); // 1
console.log(num2); // 逻辑上是2 但是吗? num2 is not defined
思考2:JS代码中的变量可以在任何地方使用/输出吗?
回答:不可以
思考:为什么?
回答:因为JS作用域
相关概念(作用域/局部/全局)
-
作用域:JS变量可以用的区域
-
局部
局部变量:指函数体内声明的变量
特性:仅函数体内使用(函数调用完毕销毁 生命周期
- 全局
全局变量:指函数体外声明的变量
特性:全局都可以使用(网页关闭销毁 生命周期
画出所有作用域
- 题目1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OKyouqmH-1624254040498)(images/1591942510219.png)]
<script>
/*
读取一个script
编译
var num
执行
num = 111;
*/
var num = 111;
console.log(num);
</script>
<script>
console.log(num);
</script>
<script>
console.log(num);
</script>
- 题目2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fTTRPOnZ-1624254040504)(images/1591942597298.png)]
<script>
var num = 111;
function fn() {
var num2 = 222;
}
console.log(num);
</script>
<script>
console.log(num);
</script>
<script>
console.log(num);
</script>
- 题目3:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QCe2HvQZ-1624254040510)(images/1591942652109.png)]
<script>
function fn1() {
}
function fn2() {
}
// 脚下留心:
// 你在【全局作用域】定义变量大家都可以用(你被锁在大房子里面 -> 所有小房子都可以进)
// 你在【fn1作用域】定义变量问fn2作用域能用吗,不能(你被锁在小房子里面->进不了其他房子)
</script>
- 题目4:思考下述代码运行结果
<script>
var num = 111; // 声明全局变量
function fn() {
var num2 = 222; // 声明局部变量
}
fn()
console.log(num); // 结果:111
console.log(num2); // 结果:报错 没有定义
</script>
隐式声明
- 隐式声明:函数体内不加var声明的变量
- 作用:等于全局变量
- 留心:全局有就修改、否则创建
- 练习
<script>
var num = 111; // 全局变量
function fn() {
var num2 = 222; // 局部变量
}
fn()
console.log(num); // 结果:111
console.log(num2); // 结果:报错
</script>
- 练习:思考下述代码结果,为什么?
案例1
<script> var num = 111; // 函数体外面,全局变量 function fn() { var num2 = 222; // 函数体内,局部变量 alert(num) // 弹111 alert(num2) // 弹222 } fn(); alert(num) // 弹全局 能 alert(num2) // 弹局部 不能 </script>
案例2
<script> var num = 111; // 全局变量 function fn() { num = 222; // 全局变量(隐式创建 alert(num) // 222 } fn(); alert(num) // 222 </script>
案例3
<script> var num = 111; // 全局变量 dataUpdate function fn() { var num2 = 222; // 局部变量 num = 'dataUpdate'; // 隐式全局变量、修改 } fn(); alert(num) // dataUpdate alert(num2) // 报错 </script>
小总结
作用域:JS变量可以使用区域
全局
全局变量:函数体外声明、函数体内不加var声明
生命周期:网页运行产生、网页关闭
局部
局部变量:函数体内加var
生命周期:函数调用创建、调用关闭销毁
三、作用域链!!!
明确需求
- 思考下述代码输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8MELQcQw-1624254040516)(images/1566519382454.png)]
- 思考:上述代码1w最终改的是谁? 1 2 3
概念
概念:多个作用域的集合
特性!!!:
当变量没加var时,会去上一级作用域中找【同名 && 带var】
找到了 - 直接修改
找不到 - 再去上一级作用域中找
一直找到顶级作用域
找到 - 直接修改
找不到 - 自己创建自己修改
画图
- 根据概念画出【明确需求】的所有作用域 、并分析输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lc6F1Y9l-1624254040517)(images/1591944189782.png)]
10000
练习
- 题目1
var num1 = 111; // 全局变量
function fn1() {
var num1 = 222; // 局部变量
}
fn1();
console.log(num1); // 结果:111
- 题目2
var num1 = 111;
function fn1() {
var num1 = 222;
function fn2() {
var num1 = 333;
}
fn2();
}
fn1();
console.log(num1); // 111
- 题目3
<script>
var num1 = 111;
function fn1() {
num1 = 222;
}
fn1();
console.log(num1); // 222
</script>
<script>
var num1 = 111; //
function fn1() {
var num1 = 222; //
function fn2() {
num1 = 333; //
}
fn2();
}
fn1();
console.log(num1); // 3 3 3 111
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-640FhtBe-1624254040519)(images/1591944829220.png)]
小总结
作用域链是什么:多个作用域的集合
作用域特性
当变量没加var时,回去上一个作用域中找【同名&带var】
找到了 - 直接修改
找不到 - 在作用域链上找
一直找到顶级作用域
找到了 - 直接修改
找不到 - 自己创建修改
四、事件!!!
明确需求
在实战工作中,用户打开网页会有很多交互,例如:鼠标放到某个图标上出现提示,点击按钮返回顶部的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xgTyNlxe-1624254040519)(images/1591938387796.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kt1H7AjR-1624254040520)(images/1591938400507.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bQr1uf5F-1624254040521)(images/1591938410069.png)]
思考:如何实现?
回答:通过js的事件技术
div 基本结构
CSS 美化网页
JS 加特效
事件概念
事件:用户和网页的交互/动作
举例:鼠标移入、点击加入购物车、点击购买数量加1
留心:交互产生后全部都是交给函数处理
事件语法
ID属性值.事件类型 = function() {
// 代码
}
##事件种类
- 鼠标
单击 onclick
双击 ondblclick
移入 onmouseover
移出 onmouseout
按下 onmousedown
松开 onmouseup
移动 onmousemove
右击 oncontextmenu content内容 context
- 键盘
按下 onkeydown
松开 onkeyup
- 表单(后续讲
表单提交 onsubmit
表单重置 onreset
失去焦点 onblur
获取焦点 onfocus
下拉改变 onchange 上传头像file 下拉框select 单独记
- 页面(后续讲
页面加载完毕执行 onload
网页尺寸改变 onresize
网页滚动条 onscroll
练习1
页面搞一个div100x100 背景绿色
实现
点击打印 你点我了
双击打印 你双击我了
移入打印 你移入我了
移除打印 你移除我了
移动打印 别乱动
<style>
div {
width: 100px;
height: 100px;
background: green;
}
</style>
<div id="box"></div>
<script>
// 概念:用户和网页之间的交互
// 场景:加入购物车、登录等等
// 语法:ID属性值.事件类型 = function(){}
// 页面搞一个div100x100 背景绿色
// 实现
// 点击打印 你点我了
box.onclick = function() {
console.log('你点我了')
}
// 双击打印 你双击我了
box.ondblclick = function() {
console.log('你双击我了')
}
// 移入打印 你移入我了
box.onmouseover = function() {
console.log('你移入我了 onmouseover')
}
// 移除打印 你移除我了
box.onmouseout = function() {
console.log('你移除我了 onmouseout')
}
// 移动打印 别乱动
box.onmousemove = function() {
console.log('别乱动 onmousemove')
}
</script>
练习2
第一个input输入数据
在
第二个input显示数据
我是第一个
<input type="text" id="input1">
<hr />
我是第二个<input type="text" id="input2">
<script>
// 监控input框按下:id属性值.onkeyup = function() {}
// 获取input框数据:id属性值.value
// 设置input框数据:id属性值.value = 值
input1.onkeyup = function() {
// console.log('你输入数据了')
// 1. 获取input1数据
var val = input1.value
// 2. 放到input2框里面
input2.value = val
}
</script>
综合案例
- 计算两个文本框的加减乘除
- 静态
<input type="text" id="input1" value="">
<select id="fuhao">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" id="input2" value="">
<button id="eqBtn">=</button>
<input type="text" id="result" value="">
- 写JS
<input type="text" id="input1" value="">
<select id="fuhao">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" id="input2" value="">
<button id="eqBtn">=</button>
<input type="text" id="result" value="">
<script>
// 1. 给 = 绑定点击事件
// 2. 事件处理函数 1 获取input1的值 2 获取input2的值 3 获取fuhao 4 放到result里面
// 1. 给 = 绑定点击事件
eqBtn.onclick = function() {
// 2. 事件处理函数 1 获取input1的值 2 获取input2的值 3 获取fuhao 4 放到result里面
var val1 = Number(input1.value)
var val2 = Number(input2.value)
var type = fuhao.value
switch (type) {
case '+':
var rs = val1 + val2
break;
case '-':
var rs = val1 - val2
break;
case '*':
var rs = val1 * val2
break;
case '/':
var rs = val1 / val2
break;
default:
var rs = '有瑕疵'
break;
}
result.value = rs
}
</script>
■ 作业
1 总结本周学习知识点,必须掌握能够口述【变量、parseInt 判断 循环 函数 事件】概念&语法
2 预习下周知识点