JS基础–JS语法
表达式与语句
表达式
- 一般来说,表达式都伴随值或返回值的存在。但这并非绝对的
- 1 + 2表达式的值是 3
- add(1,2)表达式的值为函数add()的返回值
- console.log表达式的值为console对象的log函数本身
- console.log(3)表达式的值是console.log(3)的返回值,但是因为log函数并没有设定返回值,所以JS默认返回undefined,
值是值,返回值是返回值两者并不是一个东西。
语句
- 语句的作用一般具有一定的功能,如:声明,赋值等。但这也并非绝对的
- var a = 1 这就是一个简单的语句。
表达式和语句的注意点
- JS对 大小写是敏感的 ,object和Object是不一样的 JS中大部分的 空格、回车是没有意义的,而且连续的空格、回车会被默认成1个空格。
- 但JS中有一个地方不能加回车,就是函数的return后面,return后面只能在return的同一行写返回的内容,因为return后面的内容并不执行。
- JS中的 (逗号,) 与 (分号;):逗号代表该语句还没结束,逗号可以吧多行语句连接成1行语句的效果;而分号在JS中则代表1行语句的结束。
标识符
// 一些怪异的变量名
var _ = 1
var $ = 2
var _____ = 6
var 你好 = 'hello'
注释
JS的注释有两种:单行注释和多行注释
// 单行注释
/*
多行注释
多行注释
*/
优秀的注释
- 分享开发过程踩坑的经验,前人种树后人乘凉。
- 开发过程中遇到的bug 特殊需求
区块(代码块)block
区块常常和if/while/for合用
// {} 包裹的就是一个区块
{
let a = 1
let a = 2
}
if语句
if else语句结构
if(判断条件的表达式){语句1}else{语句2}
复制代码if(){} else{} 语句整体只是“一句语句”
else if的原理
if else 后面的区块 {} 的语句“只有一句”的时候是可以省略的。
// else if 的原理
if(判断1){
语句1
}else{ // 因为else后面的 {} 中只有一个 if else 语句,所以可以省略 {}
if(判断2){
语句2
}else {
语句3
}
}
// 省略 {} 后,就是常见的 else if 结构
if(判断1){
语句1
}else if(判断2){
语句2
}else{
语句3
}
复制代码 只有在使用 else if 的时候才建议省略 {} 其他时候都不建议省略。
“只有一句”不是“只有一行”,一行里面可以有多个语句(通过 分号; 即可实现)
let a = 1
if(a ===1 )
if(a<2) // 这是一句语句
console.log(a) // 这是另一句语句,其实缩进是和 if(a ===1 ) 平级的,人造坑
// 因为 {} 省略后只会关注后面的第一行语句,所以 console.log(a) 并不在 if(a ===1 ) 代码块下面
// console.log(a) 和 if(a ===1 ) 是平级的,执行完 if(a ===1 ) 就执行console.log(a)
// 所以最终结果会输出 1
复制代码 可以通过过 逗号, 来实现多行语句合并成一行语句
//通过过 逗号, 来实现多行语句合并成一行语句
let a = 1
if(a === 1)
console.log(‘a’),console.log(‘b’)
// 因为 console.log(‘a’),console.log(‘b’) 使用逗号隔开,所以这是一行语句
// 因此结果会输出 a b
复制代码推荐的2种 if 语句写法
// 第一种
if (表达式) {
语句
} else if (表达式) {
语句
} else {
语句
}
// 第二种
function fn() {
if (表达式) {
return 表达式
}
if (表达式) {
return 表达式
}
return 表达式
}
复制代码switch语句
switch语法
switch语句整体分4部分:switch部分,case部分(所有case),执行体部分(所有执行体),break。
switch执行顺序:
将switch部分中传入的变量和case部分的值进行比对
不相等则比对下一个case部分,直至匹配到相等的case,或switch语句全部结束。
相等则进入最近的执行体执行一系列的语句,直到遇到一个break
遇到break退出switch
// 这个例子 如果 fruit = ‘lemon’ 那么最后输出的是 ‘lemon or orange’ 和 ‘peach’,原因请关注break
switch (fruit) {
case ‘banana’:
console.log(‘banana’)
break
case ‘apple’:
console.log(‘apple’)
break
case ‘lemon’:
case ‘orange’:
console.log(‘lemon or orange’)
case ‘peach’:
console.log(‘peach’)
break
}
复制代码问号冒号表达式(三元表达式)
语法&使用
三元表达式其实就是 if 语句的简写
// 三元表达式语法
(表达式1)? (表达式2) : (表达式3)
// 使用例子:求绝对值
let a = -1
let abs
// 三元表达式
abs = a>0? a : -a
console.log(abs)
// if 语句
if(a > 0){
abs = a
} else {
abs = -a
}
console.log(abs)
复制代码&& 短路逻辑
&&的执行逻辑
简单来说:在 A&&B&&C&&D的结构下,取第一个假值,或取D;注意是取值,true/false只是取值的一种情况。
&&的常用情况
// 1. console,因为IE浏览器没有console,所以通过&&来实现兼容写法
// 在IE浏览器下,因为没有console,所以直接执行console.log(‘haha’)会出现报错
// 在这种写法下,执行到console便因为是假值,而不会再向后执行,解决报错问题
console && console.log && console.log(‘haha’)
// 2. 并且判断
// 只有 a 在 1~10之间才会 console.log(a)
// a>1 a<10 返回的都是一个布尔值,所以取的也是一个布尔值
if(a>1 && a<10){
console.log(a)
}
复制代码|| 短路逻辑
||的执行逻辑
简单来说:在 A||B||C||D的结构下,取第一个真值,或取D;注意是取值,true/false只是取值的一种情况。
||常用场景
// 只有当 a 小于 1 或 a 大于 10 才会 console.log(a)
if(a<1 || a>10){
console.log(a)
}
复制代码while循环
语法&执行过程
while(表达式){语句}
复制代码执行过程:
判断表达式的真假
当表达式为真,执行语句,执行完后再判断表达式的真假
当表达式为假,跳出循环,执行后面的语句
while循环的注意点
注意循环的指标变量,循环指标(什么时候跳出循环)不要变成死循环
JS浮点数不精确,循环变成死循环
let a 0.1
console.log(a+0.1) // 多执行几次会发现结果和想象的不一样
while(a<1){
console.log(a)
a + 0.1 // 因为浮点数不精确,a最接近1的值是 0.99999999999 而不会 = 1,结果就是造成死循环
}
复制代码for 循环
for循环 与 while循环
for循环就是while循环的语法糖,它将while循环必须有的东西都包括进去了,可以有效防止人为疏忽造成的死循环.
for循环语法&执行过程
for(语句1;表达式2;语句3){
循环体
}
复制代码执行过程:
执行语句1
判断表达式2
如果2.记过为真,执行循环体,执行语句3;循环2. 3. 直到 2. 的结果为假
如果2.结果为假,直接退出循环,执行后面的语句
for循环中的循环指标变量
这里的例子涉及到 setTimeout的执行机制
setTimeout(func,time)函数运行机制
setTimeout(func,time)是在time(毫秒单位)时间后执行func函数。浏览器引擎按顺序执行程序,遇到setTimeout会将func函数放到执行队列中,等到主程序执行完毕之后,才开始从执行队列(队列中可能有多个待执行的func函数)中按照time延时时间的先后顺序取出来func并执行。即使time=0,也会等主程序运行完之后,才会执行。
for var循环 和 for let循环结果不同的原因:
for var循环本身没有块级作用域,所以 var 的指标变量存储在全局变量中,所以当调用的变量的时候,是从全局变量中获取
for let循环中,let可以构造块级作用域,所以指标变量存储在每次循环的块级作用域中,调用变量的时候从块级作用域中获取
for(var a = 1;a<5;a++){
console.log(a)
} // 输出 0 1 2 3 4
for(var a = 1;a<5;a++){
setTimeout(()=>{
console.log(a)
},0)
} // 输出5个5
for(let a = 1;a<5;a++){
setTimeout(()=>{
console.log(a)
},0)
} // 输出 0 1 2 3 4
复制代码break&continue
break:跳出整体循环(循环嵌套下,跳出的是离break最近的那个循环)
continue: 跳出本次循环,直接进入下次循环
label语句(标记语句)
label是什么?与对象的区别
MDN:标记就是在一条语句前面加个可以引用的标识符。标记语句可以和 break 或 continue 语句一起使用。可以让 break 或 continue基于标记而不是当前循环
// label
foo:{
console.log(1)
break foo;
console.log('break了。本行不输出')
}
console.log(2) // 最终输出 1 2
// 这是一个代码块,代码块内是一个标签,标签的内容是 1;而不是对象
{
foo:1
}
// 这才是对象
var a = {
foo:1
}