43. JavaScript流程控制、函数、箭头函数、对象
1. 流程控制
1.1 if判断
[1] 单if分支
if(条件){
条件成立运行的代码
}
[2] if...else分支
if(条件){
条件成立运行的代码
}else{
条件不成立运行的代码
}
var a = 10;
if (a >= 20) {
console.log("ok")
} else {
console.log("get out")
};
VM67:5 get out
[3]if...else if...else分支
if(条件1){
条件1成立运行的代码
}else if(条件2){
条件1不成立条件2成立运行的代码
}else{
条件1和2都不成立运行的代码
}
var a=15;
if (a > 20 ){
console.log("ok")
}else if(a<10){
console.log("new")
}else{
console.log("get out")
};
VM193:7 get out
1.2 switch - case 语法
[1] 概念
提前定义好可能出现的情况和运行的代码
break:如果不加break,匹配成功之后会继续运行后续case语句
default:所有条件都不成立时运行的代码
[2]代码
var num=2
switch (num) {
case 0:
console.log("Canada");
break;
case 1:
console.log("giao");
break;
case 2:
console.log("年轻有为");
break;
default:
console.log("帅");
};
VM319:10 年轻有为
1.3 while循环
while(循环条件){
循环体代码
}
var i = 0;
while (i<10){
console.log(i)
i++;
};
VM323:3 0
VM323:3 1
VM323:3 2
VM323:3 3
VM323:3 4
VM323:3 5
VM323:3 6
VM323:3 7
VM323:3 8
VM323:3 9
1.4 for循环
[1] 传统for循环(基于索引的循环)
for(初始值;循环条件;每次循环之后的操作){
循环体代码
}
打印0~9的数字
for (var i=0;i<10;i++){
console.log(i)
}
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
打印数组的每一个元素
var a=[11,22,33,44,55,66]
for(var i=0;i<a.length;i++){
console.log(a[i])
}
// 11, 22, 33, 44, 55, 66
[2] for...of 遍历元素值(ES6+)
遍历可迭代对象(数组、字符串、Map、Set等)的值:
const arr = ['a', 'b', 'c'];
for (const value of arr) {
console.log(value); // 'a', 'b', 'c'
}
// 遍历字符串
for (const char of 'hello') {
console.log(char); // h, e, l, l, o
}
// 带索引
for (const [index, value] of arr.entries()) {
console.log(index, value);
}

[3] for...in 循环
遍历对象的可枚举属性(包括原型链上的)
遍历字典时得到的是字典的键:
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
console.log(key, obj[key]); // a 1, b 2, c 3
}
遍历数组时得到的是数组的索引:
for...in 会遍历到数组原型链上的可枚举属性(比如手动给 Array.prototype 添加的方法),导致遍历结果混乱;
遍历顺序不保证严格按数组索引排序(若数组有非整数键,顺序会错乱),虽然浏览器通常按定义顺序,但不应依赖。
const arr = [10, 20, 30];
// 手动给数组原型加一个可枚举属性,会被for...in遍历到
Array.prototype.foo = "hello";
for (const key in arr) {
console.log(key, arr[key]); // 会输出 0 10 | 1 20 | 2 30 | foo hello
}
安全用法(避免遍历原型属性):
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 只遍历对象自身的属性
console.log(key, obj[key]);
}
}
[4] forEach 数组内置方法
对每个元素运行回调函数,无法中途 break 终止循环,适合纯遍历处理元素。
item:当前元素
index:当前元素索引,可选
const arr = [10, 20, 30];
arr.forEach((item, index) => {
console.log(index, item);
});

[5] jquery的循环(需要先导入)
(1) 遍历 DOM 元素集合:each 方法
针对 jQuery 选择器获取到的元素集合,是 jQuery 最常用的循环,回调内 this 指向当前 DOM 原生元素。
$("li").each(function(index, element) {
console.log(index, $(this).text());
});
$("li") 选中页面里所有 li 标签,得到 jQuery 元素集合。
each 遍历集合里的每一个 li。
每循环一次,接收两个参数:index 是当前 li 的序号,从 0 开始;element 是当前原生 DOM 元素。
$(this) 把当前原生 DOM 元素包装成 jQuery 对象,text () 读取这个 li 的文本内容。
控制台依次打印当前元素的索引和对应的文本。
作用:打印所有 li 的索引和文本,完整遍历全部元素;不会终止循环,全部运行完毕
| 参数 | 说明 |
|---|---|
| index | 当前元素在集合中的索引,从 0 开始 |
| element | 当前原生 DOM 元素,本代码未直接使用 |
| this | 原生 DOM 对象,用 $(this) 转为 jQuery 对象 |
终止循环:回调内返回 false 即可跳出整个 each,返回 true 等同于 continue,进入下一次循环。
$("li").each(function() {
if ($(this).text() === "结束") {
return false;
}
});
同样遍历所有 li 元素。
读取当前 li 的文本,判断文本是否等于 “结束”。
一旦匹配成功,执行 return false,直接终止整个 each 循环,后面的 li 不再遍历。
如果不匹配,继续进入下一个元素循环。
return false 代表终止整个循环,等同于break。
return true 代表跳过本次,继续下一轮,等同于continue。
作用:检测文本为 “结束” 的 li,找到后立刻停止遍历;会终止循环,匹配后终止。
(2) 遍历普通数组、对象:$.each 全局方法
静态方法,接收数组或对象作为第一个参数,回调参数顺序为索引、元素。
const arr = [10, 20, 30];
$.each(arr, function(index, value) {
console.log(index, value);
});

遍历对象示例:
const obj = { name: "张三", age: 18 };
$.each(obj, function(key, value) {
console.log(key, value);
});

| 参数 | 说明 |
|---|---|
| 第一个参数 | 待遍历的数组或普通对象 |
| index/key | 数组为索引,对象为属性名 |
| value | 数组元素,对象属性值 |
(3) 总结
| 方法 | 调用对象 | 适用场景 | 回调参数顺序 |
|---|---|---|---|
| $("div").each() | jQuery DOM 集合 | 遍历选中的 DOM 元素 | index, element |
| $.each() | jQuery 全局静态方法 | 遍历原生数组、对象 | index/key, value |
1. jQuery 的 each 无法用 break、continue 关键字中断,只能通过 return false 终止整体循环,return true 跳过本次迭代。
2. 现代原生 JavaScript 的 for...of、forEach 完全可以替代 jQuery 循环,仅在维护旧 jQuery 项目时使用。
2. 三元运算符
a = 1>2 ? 11:22
问号前面的条件成立则使用冒号左边的值
条件不成立使用冒号右边的值

3. 函数
3.1 函数定义
function 函数名(参数1,参数2){
函数体代码
return 返回值
}
(1)function为定义函数的关键字
(2)函数名的命名参考变量名,JavaScript推荐使用驼峰体
(3)参数可写可不写
(4)函数调用:函数名加括号,有参传参
3.2 无参函数
function f1(){
console.log("帅,年轻有为")
}
f1()
VM160:2 帅,年轻有为
3.3 有参函数
function f2(a,b) {
console.log(a,b)
}
f2() //可以调用,传了两个undefined
undefined undefined
f2(1) //可以调用,少了的参数用undefined填充
1 undefined
f2(1,2)
1 2
f2(1,2,3,4,5) //可以调用,多的参数不传入
1 2
arguments对象:接收所有的实参
function f2(){
console.log(arguments)
if (arguments.length === 0){
console.log('什么参数都没传')
}else if(arguments.length === 1){
console.log('传了一个参数')
}else{
console.log('传了多个参数')
}
}
f2(1,2,3,4,5,6)
Arguments(6) [1, 2, 3, 4, 5, 6, callee: ƒ, Symbol(Symbol.iterator): ƒ]
传了多个参数
3.4 返回值return
不支持返回多个参数


3.5 函数表达式
函数表达式是函数定义的另一种形式,就是将匿名函数赋值给一个变量
调用函数的方法是给变量名加()运行

3.6 箭头函数
[1] 概念
箭头函数是 ES6 新增的函数简写语法,使用 => 定义,本质是匿名函数,有独特的 this 绑定规则,不能当作普通函数完全等价替换 function。
[2] 参数
(1) 一个参数
以下代码表示函数接收一个参数并直接返回该参数值的情况;两种方法等价
var func1 = (v) => v; //箭头左边是形参右边是返回值
var func1 = function(v) {
return v;
};
当只有一个参数时,可以省略括号(), 但为了代码可读性,推荐保留
var f = () => 6;
// 等同于
var f = function(){
return 6
};
(2) 多个参数
多个参数括号()不能省略,参数之间用逗号,分隔,返回值后面同样跟=>
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2){
return num1 + num2;
}
// 1. 无参数
const fn1 = () => 10;
// 2. 单个参数,括号可省略
const fn2 = x => x + 1;
// 3. 多个参数,必须加括号
const fn3 = (x, y) => x + y;
// 4. 多行函数体,需要大括号,必须手动 return
const fn4 = (x, y) => {
const sum = x + y;
return sum;
};
// 5. 直接返回对象字面量,对象外层必须加圆括号
const fn5 = () => ({ name: "test" });
<script>
// 1.普通函数
function f1() {
console.log('普通函数f1')
}
f1()
// 2.匿名函数(无参数无返回值)
var f2 = function () {
console.log('匿名函数f2')
}
f2()
// 3.箭头函数(无参数无返回值)
// 去掉function,()与函数体之间加箭头
var f3 = () => {
console.log('箭头函数f3')
}
f3()
// 4.箭头函数(1个参数无返回值)
var f4 = (a) => {
console.log('箭头函数f4' + a)
}
f4(a = 'lavigne')
// 括号可以省略
var f5 = a => {
console.log('箭头函数f5' + a)
}
f5(a = 'lavigne')
// 5.箭头函数(多个参数无返回值)
// 多个参数的括号不能省略
var f6 = (a, b) => {
console.log(a + b)
}
f6(33 + 66)
// 6.箭头函数(多个参数有返回值)
var f7 = (a, b) => {
return a + b
}
// 简写
var f8 = (a, b) => a + b
console.log(f8(10 + 11))
// 7.箭头函数(一个参数有返回值)
var f9 = (a) => a + 6
console.log(f9(20))
</script>
[3] 特性
(1) this 不绑定自身
箭头函数没有独立的 this,它的 this 继承自定义时外层作用域的 this,不是调用时决定。
普通 function 的 this 由调用方式决定(对象调用、new、call 等)。
const obj = {
name: "demo",
say: function() {
const arrow = () => console.log(this.name);
arrow();
}
};
obj.say(); // demo,箭头函数this继承外层say函数的this
4. 对象
4.1 概念
JavaScript中的所有事物都是对象:字符串、数字、数组、日期等等,对象是拥有属性和方法的复合数据类型

4.2 自定义对象
[1] 对象创建
自定义对象类比于python中的字典
(1)对象字面量
使用大括号 {} 来创建一个空对象,或者初始化对象时在大括号内指定键值对。
var obj = {}
var person = { name: "avril", occupation: "singer" };
(2)构造函数new
使用 new 关键字构造函数创建新对象实例。
var obj = new Object()
[2]取值
使用变量名加点( . )调用属性

使用中括号[ ]加键名

for循环使用 · 调用属性报错案例

for in遍历得到的属性名是变量,而点语法.无法识别变量,只会把后面的内容当作固定的属性名处理。
当使用 d1.i 时,JavaScript会尝试访问对象的 "i" 属性(字面意思),而不是变量 i 的值。
4.3 日期对象Date
使用new Date()来创建当前日期和时间的对象实例

//getDate() 获取日
//getDay () 获取星期
//getMonth () 获取月(0-11)
//getFullYear () 获取完整年份
//getYear () 获取年
//getHours () 获取小时
//getMinutes () 获取分钟
//getSeconds () 获取秒
//getMilliseconds () 获取毫秒
//getTime () 返回累计毫秒数(从1970/1/1午夜)
练习:打印2017-12-27 11:11 星期三
const WEEKMAP = {
0:"星期天",
1:"星期一",
2:"星期二",
3:"星期三",
4:"星期四",
5:"星期五",
6:"星期六"
}; //定义一个数字与星期的对应关系对象
function showTime() {
var d1 = new Date();
var year = d1.getFullYear();
var month = d1.getMonth() + 1; //注意月份是从0~11
var day = d1.getDate();
var hour = d1.getHours();
var minute = d1.getMinutes() < 10?"0"+d1.getMinutes():d1.getMinutes(); //三元运算;分钟数小于10时加0展示
var week = WEEKMAP[d1.getDay()]; //星期是从0~6
var strTime = `
${year}-${month}-${day} ${hour}:${minute} ${week}
`;
console.log(strTime)
};

4.4 json对象
[1] python中
json.dumps() 序列化
json.loads() 反序列化
Supports the following objects and types by default:
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
[2] JavaScript中
JSON.stringify() 序列化(JSON必须大写)
let info = {
name:"avril",
age:20,
country:"Canada"
}
typeof info
'object'
let info_2 = JSON.stringify(info)
console.log(info_2)
VM486:1 {"name":"avril","age":20,"country":"Canada"}
typeof info_2
'string'
JSON.parse() 反序列化
console.log(info_2)
VM486:1 {"name":"avril","age":20,"country":"Canada"}
typeof info_2
'string'
let info_3 = JSON.parse(info_2)
typeof info_3
'object'
console.log(info_3)
VM706:1 {name: 'avril', age: 20, country: 'Canada'}
4.5 正则对象RegExp
[1] 创建正则表达式的两种方式
let reg = new RegExp(正则表达式);
let reg1 = /正则表达式/
[2] 代码
test()
测试字符串是否匹配正则表达式,并返回布尔值。
var reg = /^[a-zA-Z][a-zA-Z0-9]{5,9}$/;
reg.test("avril")
false
reg.test("lavigne")
true
reg.test() //空括号里的内容相当于undefined
true
//验证空括号为undefined
var reg2 = /undefined/
reg2.test("lavigne")
false
reg2.test("undefined")
true
reg2.test()
true
/g 全局标志
/g 是正则表达式中的一个标志(flag),它表示全局搜索(global search)。
当使用 /g 标志时,正则表达式会在整个输入字符串中查找所有匹配项,而不仅仅是第一个匹配项。如果没有 /g 标志,匹配操作会在找到第一个匹配项后停止。
var reg2 = /^[a-zA-Z][a-zA-Z0-9]{5,9}$/g;
// 第一次匹配:成功 -- 有数据-- 指针移动到尾端
reg2.test("lavigne")
true
reg2.lastIndex
7
// 第二次匹配:失败 -- 指针在尾端向后匹配 --无数据
reg2.test("lavigne")
false
reg2.lastIndex
0
// 第三次匹配:成功 -- 有数据-- 指针回到头部
reg2.test("lavigne")
true
reg2.lastIndex
7
// 第四次匹配:失败 -- 指针在尾端向后匹配 --无数据
reg2.test("lavigne")
false
reg2.lastIndex
0
没有/g的情形:


浙公网安备 33010602011771号