1. 函数
-
什么是: 内存中封装一项任务步骤清单的代码段, 再起一个名字
-
为什么: 代码重用
-
没有函数的弊端:
- 事件中想执行
JS脚本只能逐行编写 - 可重用性不高
- 事件中想执行
-
何时: 只要一段代码, 可能被反复使用, 都要先封装在函数中, 再反复调用函数
-
如何: 2 步
-
声明:
function 函数名(参数列表){ 函数体; return 返回值; }- 参数: 函数运行时, 接收传入函数的数据的变量, 只不过不用
var创建 - 参数列表:
- 多个参数间用逗号分隔
- 何时: 当一项任务必须某些数据才能正常执行时
- 为什么: 参数可让函数变得更灵活
- 返回值: 函数执行的结果
- 何时: 如果函数的调用者需要获得函数执行结果
- 如何返回:
return返回值- 其实,
return可单独使用 -> 退出函数 - 如果没有返回值的函数, 其实也返回东西 -> 默认返回
undefined
- 其实,
- 参数: 函数运行时, 接收传入函数的数据的变量, 只不过不用
-
调用: 让引擎按照函数的步骤清单, 执行任务
- 在任意合法的
JS脚本位置处都可以调用函数 - 语法:
函数名(参数值列表)- 参数值列表: 传入函数的执行时必须的数据列表
-
只要函数定义时规定了参数变量, 调用时传入的顺序必须保持一致
-
每个参数值之间用逗号分隔
-
- 参数值列表: 传入函数的执行时必须的数据列表
强调: 函数不调用不执行, 只有调用才执行
- 在任意合法的
-
特殊情况
-
如果一个表达式或函数有结果, 就可直接当一个值用
-
如果传入参数个数不符, 不会报错
- 个数超了, 多出的没用; 个数不够, 未接到值的参数变量, 默认值
undefined
- 个数超了, 多出的没用; 个数不够, 未接到值的参数变量, 默认值
-
在函数内, 为没有声明过的变量赋值, 变量会被自动创建在全局 -> 危险
-
强烈建议: 所有变量使用前, 必须先声明
-
-
return特点:return不能放在其他表达式中间使用
-
-
函数和方法: 都是
function对象, 函数和方法本质是一样的- 函数: 不属于任何对象的叫函数( 不需要通过 . 访问 )
- 方法: 属于特定对象的函数叫方法( 需要通过 对象**.** 才可访问 )
-
2. 作用域
-
scope: 一个变量的可用范围, 包括: 2 种
- 全局作用域:
window- 全局变量: 直接定义在全局中, 不属于任何函数的变量
- 特点: 可反复使用, 随处可用
- 何时: 如果一个变量需要反复使用, 或跨函数随处可用时
- 函数作用域:
- 局部变量: 2 种
- 函数的参数变量
- 在函数内
var出的变量
- 特点: 仅在函数内可用, 出了函数不能使用
- 不可重用
- 何时: 如果一个变量, 仅希望在函数内有效时
- 局部变量: 2 种
- 总结: 1. 优先定义并使用局部变量 2. 尽量少使用全局变量 -> 避免被污染
- 变量的使用顺序: 1. 优先使用函数内的局部变量 2. 只要局部声明了, 就不用全局的 3. 除非局部没有声明, 才去全局找
3. 声明提前( hoist )
-
什么是:
在开始执行程序前, 引擎会将
var声明的变量和function声明的函数, 提前到当前作用域顶部集中优先创建 -> 再开始执行程序, 赋值留在原地- 鄙视: 如果先使用, 后声明, 一定在考声明提前
- 就要将所有
var和function提前到当前作用域的顶部, 先创建, 再判断程序的输出
- 就要将所有
- 鄙视: 如果先使用, 后声明, 一定在考声明提前
-
解决: 变量
- 传统: 强烈建议将所有的声明都集中在当前作用域顶部
ES6+:let代替var声明变量let要求: 在let之前, 不允许提前使用该变量
-
函数:
var 函数名=function(...){...}- 本质: 函数名其实仅是一个普通的变量
- 函数其实是保存代码段的引用类型的对象
- 函数名通过函数对象的地址引用着函数对象
- 本质: 函数名其实仅是一个普通的变量
4. 按值传递
-
什么是:
两变量间赋值, 或向函数中传入参数时, 其实只是将原变量中的值复制一个副本给对方
-
结果:
- 原始类型的值: 修改新变量, 不影响原变量的值
- 引用对象的值: 按值传递, 将变量中的地址复制给对方
5. 全局函数
- 什么是:
ES标准中规定的, 不需要任何对象就可直接调用的函数- Ex:
String()/Number()/Boolean()/parseInt()/parseFloat()/isNaN() - 反例:
alert()/prompt()
- Ex:
6. 编码解码
-
什么是: 将
url中多字节字符或保留字符编码为单字节 -
为什么:
url中不允许出现多字节字符以及和保留字符冲突的字符 -
何时: 只要
url中包含多字节字符以及和保留字冲突的字符时, 都要先编码为单字节 -
如何: 1. 编码:
var code = encodeURI( url )- 解码:
var text = decodeURI( url )
- 解码:
-
问题: 不能对保留字符编码解码, Ex: ``:
,/`- 冒号在
url中区分协议名和主机名, 而斜杠用来表示路径上下级的区分 - 解决: 1. 编码:
var code = encodeURIComponent( url )2. 解码:var text = decodeURIComponent( url )
- 冒号在
7. eval 函数
-
专门执行一段字符串格式的
JS表达式, 还可计算字符串格式的表达式的值 -
普通模式下,
eval中代码的作用域就是eval所在的作用域, 在严格模式下,eval自己一个作用域,eval中声明的变量或函数在eval外不能用 -
Ex:
console.log(eval('4+7'))-> 11
8. 分支结构
-
程序三大结构: 顺序, 分支, 循环
- 顺序: 除去声明提前, 其余代码默认都从上向下顺序执行
- 分支: 根据不同的条件, 执行不同的代码操作
- 循环: 让程序反复执行一段相同代码
-
程序 = 数据结构 + 算法
-
什么是: 让程序根据不同的条件执行不同的操作
-
何时: 只要让程序根据不同的条件执行不同的操作
-
如何:
-
一个条件, 一件事, 只有满足才做, 不满足就不做
-
如果操作简单: 利用短路逻辑 -> 条件
&&( 操作1, 操作2...)- 操作可以用分号隔开写多个
-
如果操作复杂:
if(条件){操作代码段}-
满足条件就执行操作
-
条件可以是任意关系运算或逻辑运算, 只要返回
true和false的函数或表达式, 都可当条件用
-
-
-
一个条件, 二件事, 二选一执行 -> 满足条件做第一件, 不满足做另一件
- 如果仅两个值二选一:
条件 ? 值1 : 值2 - 如果操作简单: 三目 / 三元 / 条件:
条件 ? 操作1 : 操作2 - 如果操作复杂:
if (条件) { 操作1 } else { 操作2 }
- 如果仅两个值二选一:
-
多个条件, 多件事, 多选一执行
-
如果多个值, 多选一: 三目
-
条件1 ? 值1 : ( 条件2 ? 值2 : 值3 ) -
强调: 默认值不能省略
-
-
如果操作简单: 三目
条件1 ? 操作1 : ( 条件2 ? 操作2 : 操作3 ) -
如果操作复杂:
if...else if结构if(条件1){ 操作1 //如果当前条件满足,则不再向后执行 }else if(条件2){ //如果进入条件2,暗示条件1不满足 操作2 }else if(...){ ... }else{ // 如果没有默认操作,则else省略 默认操作 }- 简写: 如果
if/else if/else下只有一句话, 可省略{}
- 简写: 如果
-
-
特殊:
-
如果所有条件都是等于比较, 可简写为
switch(表达式){ //先计算表达式的值 //用表达式的值和每个case后的值做*全等*比较 case 值1: //如果表达式的值全等于case后的值 操作1; //就进入case下执行操作 break; case 值2: 操作2; break; ... default: //如果所有case的值都不等于表达式的值 默认操作; //则执行默认操作 break; }- 强调: 最后一个default可省略
-
-