js基础与语法

145 阅读4分钟

表达式 一般来说,表达式都伴随值或返回值的存在。但这并非绝对的 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行语句的结束。 标识符 标识符的规则 第一个字符可以是 1.Unicode字母(包括但不限于英文字母,拉丁字母等都在这个编码中) 2. 3.4.中文后面的字符除了上面的内容还可以是数字总之,标识符第一个字符不能是数字!!!标识符不一定是变量名,但最常见的标识符就是变量名//一些怪异的变量名var=1var3. _ 4.中文 后面的字符除了上面的内容还可以是数字 总之,标识符第一个字符不能是数字!!! 标识符不一定是变量名,但最常见的标识符就是变量名 // 一些怪异的变量名 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 }