流程控制
- 分支控制:
- if语句(if语句分为单分支,双分支,多分支)
- switch…case语句 (switch是开关的意思)
- 三元运算符(简化版的分支语句)
- 循环控制:
- 原生的 js 循环
- 使用JQuery 的遍历
分支控制
一、if分支控制
1、单分支语句
if(判断条件){
只有当if中的判断条件为true的时候,{}中的代码才会被执行,如果判断
条件不为true,则跳过{}中的代码,程序继续往下执行
}
-
if后面()中的判断条件,不管里面的表达式有多复杂,返回的值永远只有true或者false。括号内的条件为true时,进入大括号里执行代码,条件不为true,则跳过{}中的代码,程序继续往下执行 。
-
小括号内的结果若不是布尔类型时,会发生隐式转化为布尔类型。
-
如果大括号只有一个语句,大括号可以省略,但是,不提倡这么做~(虽然可以在if语句中省略大括号,但这样做可能会导致代码可读性和维护性的问题。特别是当if语句后面紧跟着一个缩进的代码块时,如果没有大括号明确定义代码块的范围,可能会引发错误。为了代码的一致性和可读性,建议始终使用大括号,即使代码块中只有一条语句。)
2、 双分支语句
if(判断条件){
如果判断条件 为true,则执行这里的代码
}else{
如果判断条件 不为true,则执行else中的代码
}
- if 可以单独使用,else必须结合if一起使用。else指的是除了满足if条件之外的所有条件。只有一行的时候可以转成三元,多行不行;
3、 多分支语句(分支语句的联级语句)
在使用if语句的时候,else的范围有时候会比较大,因此可以使用else if,对具体的情况进行细分,else if 可以根据情况设置多个。
if(判断条件){
执行语句
}slse if(判断条件){
执行语句
}else{
执行语句
}
- 注意:
0 '' null undefind
如果写在判断条件中,都被解析为false,非0 , 非'' 非null 非 undefined
如果写在判断条件中,都被解析为true。
二、switch分支控制
switch语句,特点是,默认贯穿整个结构,可以使用关键字break阻止贯穿,break的作用是阻断当前结构语句,可以阻断switch 也可以阻断 循环;
switch (数据) {
case 值1:
代码1
break;
case 值2:
代码2
break;
default:
代码n
break;
}
- 解释:
-
找到跟小括号里数据全等的case值,并执行里面对应的代码。
-
只要没有执行break,那default始终会被执行,所以break非常重要。
-
- 注意事项:
-
switch case 语句一般用于等值判断,不适合用于区间判断 。
-
switch cass 一般需要配合break关键字使用,没有break会造成case穿透。
-
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>switch语句</title>
</head>
<body>
</body>
</html>
<script>
/*
switch语句,特点是,默认贯穿整个结构,可以使用关键字break阻止贯穿
break的作用是阻断当前结构语句,可以阻断switch 也可以阻断 循环
如果没有break,default始终都会被执行
*/
let count = 70;
switch (count) {
case 30:
console.log('天涯何处无芳草');
break; //阻断switch语句,跳出switch
case 170:
console.log('一曲肝肠断');
break;
// default: 是默认的意思,如果上面的条件都不能执行则会执行default中的代码
default:
console.log('只因你太美+default');
break;
}
let num = 1;
switch (num) {
case 1:
console.log('当前是1');
num+=1
console.log(num);
case 2:
console.log('当前是2');
num++
console.log(num);
case 2:
console.log("再来一个2");
// break;
default:
num--
console.log('当前是default');
console.log(num);
break;
}
</script>
三、分支控制案例
1.在input框输入两个数字判断大小
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例</title>
</head>
<body>
数据1: <input type="number" value="" id="a" > <br>
数据2: <input type="number" value="" id="b"> <br>
<button id="bth">比较大小</button>
<hr>
</body>
</html>
<script>
let a = document.getElementById('a')
let b = document.getElementById('b')
let bth = document.getElementById('bth')
bth.onclick = function(){
let num1= a.value - 0
let num2= b.value - 0
// num1>num2? alert(num1):alert(num2)
if (num1>num2) {
alert(num1)
}else if(num2==num1){
alert('相等')
}else{
alert(num2)
}
}
</script>
2.判断闰年
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>if语句练习</title>
</head>
<body>
输入年份:<input type="number" value="" id="year" > <br>
<button id="bth2">查看是否是润年</button>
</body>
</html>
<script>
let year = document.getElementById('year')
let bth2 = document.getElementById('bth2')
bth2.onclick = function(){
let n = year.value - 0
if (n % 4 == 0 && n % 100 > 0 ||n % 400 == 0) {
alert(n+'是闰年')
}else{
alert(n+'是平年')
}
}
</script>
3.判断成绩
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>if语句练习</title>
</head>
<body>
</body>
</html>
<script>
let f = +prompt('输入考试成绩')
if (f == 100) {
alert('恭喜你的成绩为满分,奖励一个对象')
}else if (f>=90) {
alert('优秀')
}else if(f>=80){
alert('良好')
}else if(f>=70){
alert('中等')
}else if(f>=60){
alert('及格')
}else{
alert('开除学籍')
}
</script>
循环控制
一、 原生的 js 循环
1、while 循环:
While语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块。
while (条件) 语句;
// 或者
while (条件) 语句;
//举例:
var i = 0;
while (i < 100) {
console.log('i 当前为:' + i); i = i + 1;
}
2、 do……while循环
do…while循环与while循环类似,唯一的区别就是先运行一次循环体,然后判断循环条件。
do 语句 while (条件);
// 或者
do {
语句
} while (条件);
//举例:
var x = 3;
var i = 0;
do {
console.log(i); i++;
} while(i < x);
3、 for循环
语法:
for (语句 1; 语句 2; 语句 3)
{
被执行的代码块
}
-
语句 1 (代码块)开始前执行
-
语句 2 定义运行循环(代码块)的条件
-
语句 3 在循环(代码块)已被执行之后执行
案例:
for(var i=0;i<filterarray.length;i++){
alert(filterarray[i]);
}
- var i=0;:循环初始值;–开始前执行;
- i<filterarray.length;:循环条件;
- i++:在循环被执行之后执行;
- alert(filterarray[i]);:循环体
4、 增强for…in循环
fo…in循环一般用于对象的遍历。
var obj = {a: 1, b: 2, c: 3};
// 其中 obj为循环的对象, i 为对象中的“键名”。如果对象是数组,那么i就是坐标。
for (var i in obj) {
console.log('键名:', i);
console.log('键值:', obj[i]);
}
注意:
1、 任何对象都继承了Object对象,或者其它对象,继承的类的属性是默认不可遍历的,for...
in循环遍历的时候会跳过,但是这个属性是可以更改为可以遍历的,那么就会造成遍历到不属于自身的属性。
举例来说,对象都继承了toString
属性,但是for...in
循环不会遍历到这个属性。
<script>
var obj = {};// toString 属性是存在的:obj.toString
console.log(obj.toString) // ƒ toString() { [native code] }
// 下方代码就没有任何输出
for (var p in obj) {
console.log(p);
}
</script>
2、 如果继承的属性是可遍历的,那么就会被for...in
循环遍历到。但如果只想遍历自身的属性,使用for...in
的时候,应该结合使用hasOwnProperty
方法,在循环内部判断一下,某个属性是否为对象自身的属性。否则就可以产生遍历失真的情况。
var person = { name: '老张' };
for (var key in person) {
if (person.hasOwnProperty(key)) {
console.log(key); // name
}
}
3、for循环遍历json对象有点奇葩:
- 无规律json数组:JSON的键不一致;
var json = [{dd:'SB',AA:'东东',re1:123}, {cccc:'dd',lk:'1qw'}];
// 先遍历数组,拿到每一个JSON对象
for(var i=0;i<json.length;i++){
console.log("--",json[i])
// 再遍历JSON对象,拿到每一个key
for(var key in json[i]){
// 通过JSON对象的键获取值
console.log(key+':'+json[i][key])
}
}
- 有规律json数组:JSON的键一致;
packJson = [
{"name": "nikita", "password": "1111"},
{"name": "tony", "password": "2222"}
];
// 直接遍历数组,通过索引获取每一个JSON对象
for (var p in packJson) {
console.log("--",packJson[p])
// 通过JSON对象的键获取值
console.log(packJson[p].name + " " + packJson[p].password);
}
5、map()循环:
map方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。
- 注意:是返回一个新数组,而不会改变原数组。
<script>
var numbers1 = [1, 2, 3];
// function (n)的n接收的是[1, 2, 3]的每一个元素
var numbers3 = numbers1.map(function (n) {
// 每一个元素拿到之后+1
return n + 1;
}); // 最终得到一个新的数字
console.log("numbers3=",numbers3)
</script>
- map方法接受一个函数作为参数。该函数调用时,map方法向它传入三个参数:当前成员、当前位置和数组本身。
// elem:当前成员,index:当前位置,arr:数字本身
var number = [1, 2, 3].map(function(elem, index, arr) {
console.log("当前成员:",elem)
console.log("当前位置:",index)
console.log("数组本身:",arr)
return elem * index;
});
console.log("number:",number)
- map()循环还可以接受第二个参数,用来绑定回调函数内部的this变量,将回调函数内部的this对象指向第二个参数,间接操作这个参数(一般是数组)。
下面代码通过map方法的第二个参数,将回调函数内部的this对象,指向arr数组。间接操作了数组arr; forEach同样具有这个功能。
var arr = ['a', 'b', 'c'];
// [1, 2]:map方法的调用者
//function (e):接收到[1, 2]的每一个元素
// this:代表定义的arr数组
// this[e]:就是获取arr中索引为[1, 2]的值;
var new_arr= [1, 2].map(function (e) {
console.log("this[e]:",this[e])
return this[e];
}, arr)
console.log("new_arr:",new_arr)
6、forEach循环
forEach方法与map方法很相似,也是对数组的所有成员依次执行参数函数。
-
forEach方法不返回值,只用来操作数据。也就是说,如果数组遍历的目的是为了得到返回值,那么使用map方法,否则使用forEach方法。
-
forEach的用法与map方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组。
var number = [2, 5, 9].forEach(function (element, index, array){
console.log("当前成员:",element)
console.log("当前位置:",index)
console.log("数组本身:",array)
return element+1;
});
// 看一下到底有没有返回值
console.log(number) // undefined,说明还真没有返回值
- forEach循环和map循环一样也可以用绑定回调函数内部的this变量,间接操作其它变量。
var arr = ["苹果","香蕉","西瓜","李子","桃子"]
var number = [1,3].forEach(function (element, index, array){
console.log("this[element]+1:",this[element]+1)
return this[element]+1;
},arr);
// 看一下到底有没有返回值
console.log(number) // undefined,说明还真没有返回值
// 原数组还有没有改变
console.log(arr) // 没有改变,那说明forEach只是拿到元素干些事,没任何返回,对原数据也没有影响
7、filter()过滤循环
filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。
// 将大于3的数组成员,作为一个新数组返回
var num= [1, 2, 3, 4, 5].filter(function (elem) {
return (elem > 3);
})
console.log(num)
var arr = [0, 1, 'a', false];
// 将arr中为true的值重新组成一个数字
var new_arr = arr.filter(Boolean)
console.log(new_arr)
- filter方法的参数函数也可以接受三个参数:当前成员,当前位置和数字本身。
// 将大于3的数组成员,作为一个新数组返回
var num= [1, 2, 3, 4, 5].filter(function (element,index,array) {
console.log("当前成员:",element)
console.log("当前位置:",index)
console.log("数组本身:",array)
return (element > 3);
})
console.log(num)
- filter方法也可以接受第二个参数,用来绑定参数函数内部的this变量。
var obj = { MAX: 3 };
var myFilter = function (item) {
console.log(this)
if (item > this.MAX) return true;
};
var arr = [2, 8, 3, 4, 1, 3, 2, 9];
// 获取arr中大于3的数重新组成一个数组
var new_arr = arr.filter(myFilter, obj)
console.log(new_arr);
- 注意:使用第二个参数的时候好像有bug,比如下面的例子:
var arr = ["苹果","香蕉","西瓜","李子","桃子"]
// 获取arr中角标大于2的数据组成一个新数字
var new_arr = [9,5,1,2,7,3].filter(function (element,index,array){
console.log(element)
console.log(this)
console.log(typeof this)
if(element >2) return this[element]
},arr);
console.log("new_arr=",new_arr)
8、some(),every()循环遍历,检测数组是否满足某个条件
-
这两个方法类似“断言”(assert),返回一个布尔值,表示判断数组成员是否符合某种条件。
-
它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:当前成员、当前位置和整个数组,然后返回一个布尔值。
-
这两个方法在实际开发中,大有可用之处。比如在判定用户是否勾选了不可操作的数据,或者是否勾选了一条可以操作的数据可以使用这两个方法遍历循环数组。
(1)some()
some方法是只要一个成员的返回值是true,则返回值就是true,否则返回false。–只要一个成员的返回值是true,则返回值就是true。
var arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
return elem >= 3;
});
// true
(2)every()
every
方法则相反,所有成员的返回值都是true
,整个every
方法才返回true
,否则返回false
。–只要有一个是false,便返回false。
var arr = [1, 2, 3, 4, 5];
arr.every(function (elem, index, arr) {
return elem >= 3;
});
// false
9、 reduce(),reduceRight()方法可依次处理数组的每个成员
-
reduce
方法和reduceRight
方法依次处理数组的每个成员,最终累计为一个值。 -
差别是,reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样。
[1, 2, 3, 4, 5].reduce(function (a, b) {
console.log(a, b);
return a + b;
})
// 1 2
// 3 3
// 6 4
// 10 5
//最后结果:15
-
reduce
方法和reduceRight
方法的第一个参数都是一个函数。该函数接受以下四个参数。-
- 累积变量,默认为数组的第一个成员–必填
-
- 当前变量,默认为数组的第二个成员–必填
-
- 当前位置(默认从0开始)–可选
-
- 原数组–可选
-
-
reduce
方法和reduceRight
方法的第二个参数用于对累积变量指定初值。- 第二个参数相当于设定了默认值,处理空数组时尤其有用,可避免一些空指针异常。
[1, 2, 3, 4, 5].reduce(function (a, b) {
return a + b;
}, 10);
// 25
- 由于这两个方法会遍历数组,所以实际上还可以用来做一些遍历相关的操作。比如,找出字符长度最长的数组成员。
- 下面代码中,
reduce
的参数函数会将字符长度较长的那个数组成员,作为累积值。这导致遍历所有成员之后,累积值就是字符长度最长的那个成员。
- 下面代码中,
function findLongest(entries) {
return entries.reduce(function (longest, entry) {
return entry.length > longest.length ? entry : longest;
}, '');
}
findLongest(['aaa', 'bb', 'c']) // "aaa"
10、 Object.keys遍历对象的属性
Object.keys
方法的参数是一个对象,返回一个数组。该数组的成员都是该对象自身的(而不是继承的)所有属性名,且只返回可枚举的属性。
var obj = {
p1: 123,
p2: 456
};
Object.keys(obj) // ["p1", "p2"]
11、 Object.getOwnPropertyNames()
遍历对象的属性
Object.getOwnPropertyNames
方法与Object.keys
类似,也是接受一个对象作为参数,返回一个数组,包含了该对象自身的所有属性名。但它能返回不可枚举的属性。
var a = ['Hello', 'World'];
Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]
上面代码中,数组的length
属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames
方法的返回结果中。
- 由于 JavaScript没有提供计算对象属性个数的方法,所以可以用这两个方法代替。
<script>
var obj = {
p1: 123,
p2: 456
};
Object.keys(obj).length // 2
Object.getOwnPropertyNames(obj).length // 2
console.log(obj.length) // undefined
</script>
12、 以上循环特征(相同与不同):
1:map(),foreach,filter循环的共同之处:
-
foreach,map,filter循环中途是无法停止的,总是会将所有成员遍历完。
-
他们都可以接受第二个参数,用来绑定回调函数内部的this变量,将回调函数内部的this对象,指向第二个参数,间接操作这个参数(一般是数组)。
2:map()循环和forEach循环的不同:
- forEach循环没有返回值;map,filter循环有返回值。
3:map(环和filter()循环都会跳过空位,for和while不会
- 下面代码中,map方法不会跳过undefined和null,但是会跳过空位。forEach方法也会跳过数组的空位,这里就不举例了。
var f = function (n) {
return 'a'
};
[1, undefined, 2].map(f) // ["a", "a", "a"]
[1, null, 2].map(f) // ["a", "a", "a"]
[1, , 2].map(f) // ["a", , "a"]
4:some()和every():
- some()只要有一个是true,便返回true;而every()只要有一个是false,便返回false.
5:reduce(),reduceRight():
- reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员)。
6:Object对象的两个遍历Object.keys与Object.getOwnPropertyNames:
- 他们都是遍历对象的属性,也是接受一个对象作为参数,返回一个数组,包含了该对象自身的所有属性名。但Object.keys不能返回不可枚举的属性;Object.getOwnPropertyNames能返回不可枚举的属性。
二、 使用JQuery 的遍历
1、 $.grep()筛选遍历数组
- grep()循环能够遍历数组,并筛选符合条件的元素,组成新的数组,并返回。
function(){
var array = [1,2,3,4,5,6,7,8,9];
var filterarray = $.grep(array,function(value){
return value > 5;//筛选出大于5的
});
for(var i=0;i<filterarray.length;i++){
alert(filterarray[i]);
}
for (key in filterarray){
alert(filterarray[key]);
}
}
2、 $.each()筛选遍历数组或json对象
function(){
var anObject = {one:1,two:2,three:3};//对json数组each
$.each(anObject,function(name,value) {
alert(name);
alert(value);
});
var anArray = ['one','two','three'];
$.each(anArray,function(n,value){
alert(n);
alert(value);
});
}
3、 $.inArray()筛选遍历数组
- inArray()循环能返回参数在数组中对应的坐标。
function(){
var anArray = ['one','two','three'];
var index = $.inArray(‘two’,anArray);
alert(index);//返回该值在数组中的键值,返回1
alert(anArray[index]);//value is two
}
4、 $.map()筛选遍历数组
- 写法一:
$().ready(
function(){
var strings = ['0','1','2','3','4','S','6'];
var values = $.map(strings,function(value){
var result = new Number(value);
return isNaN(result) ? null:result;//isNaN:is Not a Number的缩写
});
for (key in values) {
alert(values[key]);
}
});
- map循环常用语往数组中添加新元素,第二种写法:
- map() 把每个元素通过函数传递到当前匹配集合中,生成包含返回值的新的 jQuery 对象。此用法与原生js的map循环用法一致。
this.detEntityList.map(item => {
//往比遍历到的对象中添加属性
Object.assign(item, {
sourceType: item.businessType,
})
});