声明提升
<!-- ! 回车 能生成基本的HTML文档代码 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>声明提升 09:30</title>
</head>
<body>
<!-- JS的v8引擎设计的过于智能, 会偷偷的修改用户的代码, 变更为标准的模式, 然后再执行 -->
<script>
// log
// 案例: 隐式类型转换
// 数学表达式中, 理论上值都是数字类型, 其他类型是错误的
// JS引擎: 揣摩你的意思, 然后偷偷修正代码
console.log(true + 4, '666' * 3)
// 假设:
var a = '44'
var b = 66
// 运算符+ : 有两种作用 - 数字相加, 字符串拼接
// JS引擎: 字符串 + 数字 的场景, 采用拼接方式2
console.log(a + b) //110??
if (4 + 5) { }
// 在非智能引擎的语言中, 代码必然是顺序执行
// 例如 java c, 下方答案是 1 2
// JS智能: 理论上必须先声明变量,函数, 然后再使用
// 但是: JS引擎为了程序员友好, 自动把错误的代码改成对的
// 这种智能的提升机制: 称为 声明提升 操作
ab()
function ab() {
console.log(33);
}
function show() {
console.log(1)
}
show()
function show() {
console.log(2);
}
show()
console.log(true + 4);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>声明提升 10:19</title>
</head>
<body>
<script>
// 声明提升: 一个JS引擎的智能操作 -- 把错的代码自动修正
// 错误写法: 先使用变量/函数, 然后再声明
// 理论上: 必须先声明变量/函数, 然后再使用
// 面试时, 经常会问一些 错误写法 会导致的结果 这种问题
console.log(a)
// 这是简写, 完整格式 var a; a = 5;
// 声明变量a , 给a赋值5
var a = 5
function a() {
console.log(6)
}
console.log(a)
a()
</script>
</body>
</html>

作用域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>作用域 10:38</title>
</head>
<body>
<script>
// JS的作用域共有4个
// 旧的: 全局 局部
// 新的: 脚本 块级
// 宿主环境: 寄生关系
// JS语言本身具有一些语法, 在不同的环境中可以使用所在环境提供的一些资源
// JS有两个宿主环境
// 1. node.js : 提供服务器相关的API -- 技能
// 2. 浏览器: 提供了一些操作浏览器相关的API -- 技能
console.log(window)
// window.alert('Hello !')
// 全局对象 window : 用于存储系统提供的API的对象
// 在脚本中直接声明的值 都会存储在 全局对象里
var a = 10
function bb() { }
// 浏览器的功能: 在后台点击 三角符号, 展开对象时, 会临时读取最新的内容
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>函数/局部作用域 10:53</title>
</head>
<body>
<script>
// 函数分两种状态
// 1. 静态: 存放状态
function show() {
// 函数在运行时, 会临时创建一个对象, 来保存声明的变量
// 临时生成的对象: 局部作用域对象
var a = 5
var b = 10
console.log(a + b)
// 浏览器提供断点功能: 可以让JS代码暂停在某个时间点; 便于程序员观察
}
// 2. 动态: 利用()触发, 函数体{} 才能执行
show()
</script>
</body>
</html>
断点


全局污染的解决
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全局污染的解决方案 11:26</title>
</head>
<body>
<script src="./shixu.js"></script>
<script src="./yueming.js"></script>
<script>
// 全局对象: window -- 存放系统提供的api
// 在脚本中 var声明的变量 或函数, 会存储在window里
// 全局变量污染: 把自定义的变量 存储在window对象
// 做法: 利用匿名函数自调用(最简单快捷) 快速搭建一个函数作用域
// 团队合作时, 一定存在大量的外部 .js 文件; 如果保证多个JS文件中声明的变量名不重复??
// 开局先写 匿名函数自调用, 在这个函数作用域中书写代码; 因为函数作用域是独立的, 所以互相不会影响
(function () {
var a = 10
function b() { }
})()
console.log(window);
</script>
</body>
</html>
shixu.js
;(function () {
const uname = '世宇'
console.log(uname)
})()
yueming.js
;(function () {
const uname = '月明'
console.log(uname)
})()
原型链
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>作用域链 11:46</title>
</head>
<body>
<script>
// 作用域链: 当多层作用域嵌套时, 当使用变量时, 会按照就近原则到上层作用域查找
var x = 10
function a() {
var x = 20
function b() {
// var x = 30
function c() {
// var x = 40
console.log(x) //打印x
}
c()
}
b()
}
a()
</script>
</body>
</html>
闭包
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>闭包 14:25</title>
</head>
<body>
<script>
function displayName() {
var uname = '亮亮'
function a() {
console.log('uname:', uname)
}
// scopes: 作用域们
// 当函数中使用到来自其他作用域的变量, 为了预防这些作用域被销毁而导致自身运行失败
// 会保存一份用到的作用域 在自身的scopes 属性里
// 闭包Closure: 一个函数作用域 被其他函数保存, 则被称为闭包
// 闭包这个称呼就是表达一种关系: 1个函数作用域 被保存到另一个函数作用域中的称呼
// 类似 : 晓宇老师 嫁人以后, 对于其丈夫来说, 就是妻子
// dir: direct 直接
console.dir(a) // 打印出函数本身 对象类型
// log: 会输出美化后的代码, 不是函数的原来模样
return a
}
var a = displayName()
a() //问: 是否能打印出uname
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>闭包的应用: 私有 14:45</title>
</head>
<body>
<script>
// 闭包: 把一个函数作用域 保存到自己的scopes中, 实现私有
// 案例: 记录一个函数的调用次数
// 改成局部 私有: 全局无法用
var show = (function () {
var num = 0
function show() {
num++
console.log('调用次数:', num)
}
console.dir(show) // 在scopes 里 找到num
return show //暴露出去
})()
show()
show()
// 全局区 没有办法能修改 局部作用域中的num
num = 1000
show()
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>闭包练习 15:20</title>
</head>
<body>
<script>
// 闭包: 对函数作用域在固定场景下的称呼
// 场景: 当函数作用域对象 被其他函数 保存在scopes 之后
// 作用: 私有
// 固定语法:
// 匿名函数自调用语法: 最快捷的创造局部作用域的语法
var funcName = (function () {
// 这里的变量属于局部作用域, 不在全局区, 非共享 -私有
var a = 10
var b = 20
return function () {
a += 2
console.log(a + b)
}
})()
funcName()
funcName()
funcName()
</script>
</body>
</html>
arguments
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>函数参数 15:41</title>
</head>
<body>
<script>
// 函数根据参数可以分为: 无参数 单参数 多参数 不固定数量
function show() {
console.log(new Date().toLocaleTimeString())
}
show()
show()
show()
function toUpper(words) {
console.log(words.toUpperCase())
}
toUpper('mike')
toUpper('paopao')
function add(x, y, z) {
console.log(x + y + z)
}
add(10, 20, 30)
////////////////////////////////////////
// 求最大值
var x = Math.max(10, 34, 545, 675, 67)
console.log(x)
var x = Math.max(10, 3, 45, 5, 56, 34, 545, 75, 67)
console.log(x)
var x = Math.max(10, 6, 67)
console.log(x)
///////////////////////////////////////
// 实参不固定的函数 如何制作?
function max() {
// 系统关键词 arguments -- 函数中自带的
// 作用: 保存收到的所有实参
console.log('arguments:', arguments)
// for循环遍历, 找出最大的
// 暂定第一个值最大
var m = arguments[0]
for (var i = 1; i < arguments.length; i++) {
var value = arguments[i]
// 实际开发中, 程序员的优良传统: 懒!
// 语法糖: if的{}只有一行代码, 可以省略{}
if (value > m) m = value
}
console.log('最大值:', m)
}
max(12, 3, 4)
max(12, 3, 4, 4, 65, 67, 78, 87)
</script>
</body>
</html>
函数重载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>函数的重载 16:23</title>
</head>
<body>
<script>
// 函数重载: 制作多功能函数 - 根据实参的个数 或 类型不同, 完成不同的逻辑操作
// 计算折扣金额
function zhekou(money) {
console.log(arguments)
//3个参数代表满减
if (arguments.length == 3) {
var man = arguments[1]
var jian = arguments[2]
if (money >= man) money -= jian
console.log('满减后:', money)
}
//如果2个参数
if (arguments.length == 2) {
if (typeof arguments[1] == 'string') {
if (arguments[1] == 'vip1') money *= 0.9
if (arguments[1] == 'vip2') money *= 0.8
console.log('vip打折:', money)
}
if (typeof arguments[1] == 'number') {
money *= arguments[1]
console.log('打折后:', money)
}
}
}
//用法:
zhekou(3000, 0.7) //3000元 打七折
zhekou(3000, 2000, 500) // 3000元 满2000减500
zhekou(3000, 'vip1') // 9折
zhekou(3000, 'vip2') // 8折
</script>
</body>
</html>
练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>练习 16:45</title>
</head>
<body>
<script>
// 计算 1 - 100 所有数字之和
for (var sum = 0, i = 1; i <= 100; i++) {
sum += i
}
console.log(sum)
// 制作一个函数, 按照要求获取总和
function getSum() {
if (arguments.length == 0) {
for (var i = 1, sum = 0; i <= 100; i++) {
sum += i
}
console.log(sum)
}
if (arguments.length == 1) {
for (var i = 1, sum = 0; i <= arguments[0]; i++) {
sum += i
}
console.log(sum)
}
if (arguments.length == 2) {
for (
var i = arguments[0], sum = 0;
i <= arguments[1];
i++
) {
sum += i
}
console.log(sum)
}
}
getSum() //获取 1 - 100 总和
getSum(200) // 获取 1 - 200 总和
getSum(300) // 获取 1 - 300 总和
getSum(20, 222) //获取 20 - 222 的总和
getSum(50, 122) //获取 50 - 122 的总和
</script>
</body>
</html>
this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>this关键词 17:20</title>
</head>
<body>
<script>
// 函数和对象类型搭配使用的两种办法
var r1 = { length: 10, width: 20 }
var r2 = { length: 40, width: 100 }
// 制作一个函数计算出 矩形的面积
function area(r) {
console.log(r.width * r.length)
}
area(r1)
area(r2)
// 固定的函数: 接收变化的参数
// 函数和对象配合的用法可以是双向的:
// 方案1: 把对象作为参数 传递到函数里
// 方案2: 把 函数作为属性 传递到 对象里
function mianji() {
// this: 这个; 所在的这个对象
// this关键词很灵活: 取决在哪个对象里执行, 就是哪个对象
console.log(this.width * this.length)
console.log('this:', this)
}
// 把mianji函数存入到 r1 对象里
r1.mianji = mianji
console.log(r1)
r1.mianji()
r2.mianji = mianji
r2.mianji()
</script>
</body>
</html>
call
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>函数call方法 17:39</title>
</head>
<body>
<script>
var r1 = { length: 10, width: 20 }
function area() {
console.log(this.length * this.width)
}
// 常规流程: 存入对象 -> 执行 -> 删除
r1.area = area
r1.area()
// 送走
delete r1.area //delete删除, 从r1中删除area
console.dir(area) //cdi
// 函数具有一个call方法: 短暂拜访
// 自动临时存储在对象里, 执行完, 就撤退
area.call(r1)
// area函数.短暂拜访(r1对象)
console.log(r1)
</script>
</body>
</html>
知识点总结
- 声明提升/隐式类型转换
- JS引擎的智能操作: 把错误的代码
偷偷的改成 对的代码
- JS引擎的智能操作: 把错误的代码
- 作用域
- 全局: window对象
- 局部: 函数运行时产生的对象, – 通过
断点功能才能看到- 利用匿名函数自调用 可以快速形成局部作用域, 避免全局污染 和 同名冲突问题
- 作用域链: 就近原则, 使用距离最近的作用域中的变量
VSCode
由微软公司出品的 世界范围内 占有率第一的 轻量级开发软件
- 拥有丰富的插件, 可以根据需求按照


格式化插件 : 让多人开发时, 编码风格保持一致!

相关配置:
-
设置文件采用 Prettier 实现格式化操作(
每种类型的文件都要设置一次, 例如 css js)


-
保存时自动格式化

-
配置插件
文件->首选项->设置->扩展->Prettier

总结
- JS的引擎是智能的, 可以自动帮用户把错误代码改正确
- 隐式类型转换: 把错误的数据类型 转为 合理的
- 声明提升: 理论上必须 先声明 再使用
- 系统会自动把所有声明提升到最上方: 函数优先变量, 变量只提升声明 不提升赋值
- 作用域
- 全局: 浏览器中是window对象, 存放系统api
- 局部: 函数运行时诞生的作用域
- 需要断点技术 才能查看
- 利用局部作用域 避免全局变量污染 和 外部JS文件中的变量冲突
- 作用域链
- 使用变量时, 会从最近的作用域中查找使用
- 闭包: 对函数作用域在特殊场景下的称呼
- 函数作用域被保存在 其他函数的scopes属性里
- 目的: 防止释放销毁, 导致不可使用
- 应用: 制作私有的变量
- arguments: 关键词
- 接收传入的所有实参
- 应用: 函数重载 – 通过判断实参的个数或类型不同, 做不同的任务
- this: 代表函数运行时所在的对象
- 函数和对象有了新的用法: 函数放到对象里执行
- call: 函数的call方法, 快速把 函数放到对象里执行, 执行完自动删除
9608

被折叠的 条评论
为什么被折叠?



