程序结构分为顺序结构、分支结构、循环结构,通常伴随着这几种程序结构存在的还有流程控制语句;
在ECMA-262规定来一组流程控制语句,语句定义了ECMAScript中的主要语法,语法通常由一个或多个关键字来完成给定的任务,例如:判断、循环、退出等;
语句:在ECMAScript之中,所有的代码都是由语句来构成都。语句表明执行过程中都流程、限定与约定,形式上可以是单行语句,或者由一对大扩号{}
括起来都复合语句,在语法描述之中,复合语句整体可以作为一个单行语句处理;
语句的种类:
1、声明语句
变量声明语句、标签声明语句
2、表达式语句
变量赋值语句、函数调用语句、属性赋值语句、方法调用语句
3、分支语句
条件分支语句、多重分支语句
4、循环语句
for、for…in、for…of、while、do…while
5、控制结构
继续执行子句、终端执行子句、函数返回子句、异常触发子句、异常捕获与处理
6、其他语句
空语句;
、with
语句、debugger
语句
顺序结构是最为简单的结构,程序自上而下依次执行的结构就成为顺序结构
程序结构分为顺序结构、分支结构、循环结构,通常伴随着这几种程序结构存在的还有流程控制语句
随着条件的不同,我们可以由if结构、if…else…结构、if…else if…else结构。
在if语句的括号里的表达式会进行自动转换为Boolean类型,如果为true,则执行后面一条语句,否则不执行后面那一条语句;
在if条件成立之后,只执行其后的一条语句,如果要执行多条语句,那么必须使用{}
包含在内,形成一个代码块;
if(表达式)[{]
// 循环体;
[}]
大括号不存在,则循环体为单行语句,否则为复合语句;
if(表达式) {
// 表达式为true执行的位置
} else {
// 表达式为false执行的位置
}
if(表达式1) {
// 表达式1为true执行的位置
}else if(表达式2) {
// 表达式1为false,表达式2为true执行的位置
}... else{
// 表达式n-1为false,表达式n为true执行的位置
}
条件表达式?成立执行的表达式:不成立执行的表示;
switch(表达式){
case 值1:语句1;[break;]
case 值2:语句2;[break;]
case 值3:语句2;[break;]
case 值n:语句2;[break;]
[default:] //都不匹配执行的语句;
}
注: switch
语句会先计算表达式,然后在每个case
语句去比较表达式的值,使用严格运算符(===
),并将控制权转换给该子句;如果都没有则执行defualt
子句,然后switch
语句执行结束,defualt
子句是最后一个子句,但不是必须的;
break
语句是可选的,该语句确保可以在相关的case
语句执行后,结束switch
之后的语句,如果省略,则会继续执行switch
语句中的下一条语句;
defualt
语句的顺序不是固定的,可以在case
之前;
在case
表达式之中可以使用复杂的运算
while
语句while(表达式) {
// 循环体
}
while
语句中的表达式,也会自动进行类型转换,转换为Boolean类型,当表达式为true
的时候,则执行循环体中的内容,否则不执行;
do..while
语句do {
// 循环体
}while(表达式);
do..while
语句先运行循环体,在判断,所以该语句结构,不管表达式是否成立,都会执行一次,循环体至少执行一次;
for
语句for ([initialization]; [condition]; [final-expression]){
// 循环体
}
for循环也被成为for i循环,通常的用法如下
for(var i = 0 ;i < 条件; i++){
// 循环体
}
for...in...
语句for (variable in object) {...}
或者兼容性表达式
for (var variable in object) {...}
注:
for...in...
可以任意顺序遍历一个对象的可枚举属性,包括原型,对于每个不同的属性,语句都会被执行;for...in...
只遍历可枚举属性;// for in 遍历对象
var personObj = {
name:"xiaojia",
age:26,
hobby:'football,programming',
test:function(){
console.log("111");
}
}
for(var key in personObj){
console.log(key,personObj[key]);
}
/* 以下为输出结果
name xiaojia
age 26
26
hobby football,programming
football,programming
test function (){
console.log("111");
}
*/
// for in 遍历数组
var arr = ["xiaojia",26,"编程"]
for(var key in arr){
console.log(key,arr[key]);
}
/* 以下为输出结果
0 xiaojia
1 26
2 编程
*/
for...in...
潜在问题与解决方案1、for...in...
只遍历可枚举的属性,包括继承来的属性,不可枚举的属性在重写之后,也变得可枚举,此时可以使用hasOwnProperty()
或者Object.defineProperty
来解决;
Object.prototype.test = "test1";
Array.prototype.test2 = "test2";
Object.prototype.say1 = function(){
console.log("你好");
};
Array.prototype.say2 = function(){
console.log("你好");
};
var arr = ["xiaojia",26,"编程"]
for(var key in arr){
console.log(key,arr[key]);
}
/*
0 xiaojia
1 26
2 编程
test2 test2
say2 function (){
console.log("你好");
}
test test1
say1 function (){
console.log("你好");
}
*/
显然,我们就出现了不属于数组的属性,而是Object继承而来的,我们这里也输出了;解决方案就是使用hasOwnProperty()
或者Object.defineProperty
来解决;
// 解决方法一:
Object.prototype.test = "test1";
Array.prototype.test2 = "test2";
Object.prototype.say2 = function(){
console.log("你好");
};
Array.prototype.say3 = function(){
console.log("你好");
};
var arr = ["xiaojia",26,"编程"]
for(var key in arr){
if(arr.hasOwnProperty(key)){
console.log(key,arr[key]);
}
}
/*
0 xiaojia
1 26
2 编程
test2 test2
say2 function (){
console.log("你好");
}
test test1
say1 function (){
console.log("你好");
}
*/
// 解决方法二:使用Object.defineProperty来解决(支持IE9,也支持IE8,但是只支持Dom对象和非标准行为)
Object.defineProperty(Object.prototype,'say',{
value:function(){
console.log('say1!');
},
enumerable: false //让say属性不可枚举,需设置enumerable属性值为false
});
Object.defineProperty(Array.prototype,'say',{
value:function(){
console.log('say2!');
},
enumerable: false //让say属性不可枚举,需设置enumerable属性值为false
});
var arr = ["xiaojia",26,"Java开发工程师"]
for(var key in arr){
console.log(key,arr[key]);
}
/*
0 xiaojia
1 26
2 编程
*/
2、for...in...
在遍历数组的时候,key为string,而不是int类型;
// for in 存在的问题2
Object.defineProperty(Object.prototype,'say',{
value:function(){
console.log('say1!');
},
enumerable: false //让say属性不可枚举,需设置enumerable属性值为false
});
Object.defineProperty(Array.prototype,'say',{
value:function(){
console.log('say2!');
},
enumerable: false //让say属性不可枚举,需设置enumerable属性值为false
});
var arr = ["xiaojia",26,"编程"]
for(var key in arr){
console.log(typeof key);
}
/*
string
string
string
*/
for...of...
语句(ES6语法)for (variable of iterable) {
//statements
}
注: 此为ES6的语法结构,for...of...
在可迭代对象(Array
、Map
、Set
、String、TypedArray
、arguments
等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
由于for...in
结构存在问题,所以ES6就推出来一个for..of
语法
Object.defineProperty(Object.prototype,'say',{
value:function(){
console.log('say1!');
},
enumerable: false //让say属性不可枚举,需设置enumerable属性值为false
});
Object.defineProperty(Array.prototype,'say',{
value:function(){
console.log('say2!');
},
enumerable: false //让say属性不可枚举,需设置enumerable属性值为false
});
var arr = ["xiaojia",26,"编程"]
for(var value of arr){
console.log(value,typeof value);
}
/*
xiaojia string
26 'number'
编程 string
*/
注: IE不兼容,edge12兼容
当条件的恒成立的时候,就构成来死循环了;
for...of...
与for...in...
的区别结论:
1、for...in...
循环的是key,for...of...
循环的是value
2、推荐在循环对象属性的时候,使用for...in...
,在遍历数组的时候使用for...of...
或fori
或者Array.prototype.forEach()
3、for...of...
是ES6新引入的特性,修复了ES5的for...in...
的不足
4、for...of...
不能循环普通的对象,需要通过和Object.keys()
搭配使用
5、for...of...
不兼容IE,for...in...
兼容ie6
break用于终止switch语句的执行,和跳出当前循环,也可以跳出指定标号位置的循环;
continue用于结束当前循环,继续下一轮循环;
所谓标号,就是label:
,一般就是为某个代码段设置一个标记,方便break和continue能够跳出或结束多层循环, 而不仅仅是当前层循环;