JS 的基本语法
表达式和语句
表达式(expression)
- 表达式,指一个为了得到一个值的计算式
- 函数的值也称为返回值
举例:
- 1+2表达式的值是3
- add(1,2)表达式的值为函数的返回值
- console.log表达式的值为函数本身
- console.log(3 )表达式的值是undefined,表达式显示的内容是3
语句(statement)
- 语句是为了完成某种任务而进行的操作
- 语句一般会改变环境(比如声明、赋值)
- 语句以分号或者空格结尾,一个分号或者空格就表示一个语句结束。
- js代码不用写分号不用不用,只有立即执行函数前面需要
- 多个语句可以写在一行内。
- 如果语句间用逗号连接,表示一个语句。
举例:
var a = 1 + 3;
这条语句先用var命令,声明了变量a,然后将1 + 3的运算结果赋值给变量a。
表达式和语句的区别
- 只有函数有返回值,函数也有值,函数的值就是他的返回值,但是一般的表达式不能说返回值,只能说值
- 语句主要是用来改变环境的,所以很多语句的值都是undefined,表达式才主要是用来取值的
- 表达式一般都有值,语句可能有可能没有
注:
- JS对大小写敏感
- 大部分空格是没有实际意义的
- 加回车大部分时候也不影响(只有return后边不能加回车)
标识符
标识符(identifier)指的是用来识别各种值的合法名称。最常见的标识符就是变量名,以及后面要提到的函数名。JavaScript 语言的标识符对大小写敏感,所以a和A是两个不同的标识符。
标识符有一套命名规则,不符合规则的就是非法标识符。JavaScript 引擎遇到非法标识符,就会报错。
规则
- 第一个字符,可以是Unicode字母或者$或_或中文
- 后面的字符,除了上边所说,话可以是数字
变量名是标识符
- var _ = 1
- var $ = 2
- var _____ =6 这样用会被打
- var 你好 = 'hi'
- 还有其他格式
合法标识符
arg0 _tmp $elem π
不合法标识符
1a // 第一个字符不能是数字 23 // 同上 *** // 标识符不能包含星号 a+b // 标识符不能包含加号 -d // 标识符不能包含减号或连词线
中文是合法的标识符,可以用作变量名。
var 临时变量 = 1;
JavaScript 有一些保留字,不能用作标识符:arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield。
注:报错样式
Uncaught SyntaxError: Unexpected token xxx( 未捕捉的语法错误:xxx不是我们所期待的字符串)
注释
- 定义:源码中被 JavaScript 引擎忽略的部分就叫做注释
- 作用:对代码进行解释
- 写法: 一种是单行注释,用//起头
- 另一种是多行注释,放在/和/之间。
// 这是单行注释 /* 这是 多行 注释 */
注释的分类:
不好的注释:
- 把代码翻译成中文
- 过时的注释
- 发泄不满的注释
好的注释:
- 踩坑注解
- 为什么代码会写得奇怪,遇到什么bug
区块
1.JavaScript 使用大括号,将多个相关的语句组合在一起,称为“区块”(block)。
{ let a=1 let b=1 }
2.对于var命令来说,JavaScript 的区块不构成单独的作用域(scope)。
{ var a = 1 } a // 1
上面代码在区块内部,使用var命令声明并赋值了变量a,然后在区块外部,变量a依然有效,区块对于var命令不构成单独的作用域,与不使用区块的情况没有任何区别。
3.在 JavaScript 语言中,单独使用区块并不常见,区块往往用来构成其他更复杂的语法结构,比如for、if、while、function等。
条件语句
if结构
1.规则
- 先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句。
- 所谓布尔值,指的是 JavaScript 的两个特殊值,true表示真,false表示伪。
- 如果表达式的求值结果为true,就执行紧跟在后面的语句;如果结果为false,则跳过紧跟在后面的语句。
2.基本形式
if (表达式){ 语句 }
3.关于 =
- 赋值表达式(=):x=y 把y的值赋给x!一直是true!
- 严格相等运算符(===):x===y x等于y 优先采用
- 相等运算符(==): x===y x等于y
if...else 结构:
if代码块后面,还可以跟一个else代码块,表示不满足条件时,所要执行的代码。
1.规则:
- 先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句。
- 如果表达式的求值结果为true,就执行紧跟在表达式后面的语句1;如果结果为false,则执行else里的语句2
2.基本形式
if (表达式){ 语句1 } else{ 语句2 }
3.语句1里面可以有嵌套的if...else 结构
var m = 1; var n = 2; if (m !== 1) if (n === 2) console.log('hello'); else console.log('world');
上面代码不会有任何输出,else代码块不会得到执行,因为它跟着的是最近的那个if语句,相当于下面这样。
if (m !== 1) { if (n === 2) { console.log('hello'); } else { console.log('world'); } }
4.语句2里面可以有嵌套的if...else 结构
// 对一个变量多次进行判断 if (表达式一) { 语句一; } else { if (表达式二) { 语句二; } else { if (表达式三) { 语句三; } else { 语句四; } } } // 去掉一些大括号,等同于 // 最推荐写法 if (表达式一) { 语句一; } else if (表达式二) { 语句二; } else if (表达式三) { 语句三; } else { 语句四; } function fn(){ if (表达式) { return表达式 } if (表达式) { return表达式 } return表达式 }
5.else代码块总是与离自己最近的前面的那个if语句配对。
6.缩进也可以很变态,如面试题常常下套
a=1 if(a===2) console.log('a') console.log( 'a等于2') // a等于2 等同于 a=1 if(a===2){ console.log('a') } console.log( 'a等于2')
程序员戒律:使用没有歧义的写法
最推荐的写法
if(表达式){ 语句 }else if(表达式){ 语句 } else { 语句 }
次推荐写法
function fn(){ if (表达式){ return 表示式 } if (表达式){ return 表达式 } return 表达式 }
return包含后面都不执行的意思,所以此时可以省略else,因为else的意思就是如果前面都没执行,就执行else之后的。
switch语句(不推荐)
1.基本结构
switch (fruit) { case "banana": // ... break; case "apple": // ... break; default: // ... }
上面代码根据变量fruit的值,选择执行相应的case。如果所有case都不符合,则执行最后的default部分。
注:
- 大部分时候,省略break,你就完了
- 少部分时候,需要使用break
问好冒号表达式
1.基本形式
(表达式) ? 语句1 : 语句2
2.规则:如果“表达式”为true,则执行“语句1”,否则执行“语句2”
举例:
function max(a,b){ if(a>b)return a; else return b; } //等同于 function max(a,b){ return a>b ? a:b }
注: 能用问号冒号表达式的时候就不用if...else
&&短路逻辑
也是用来替代if else
A && B && C && D 取第一个假值或D,并不会取true或false
举例:
if(window.f1){ console.log('f1存在') } //等同于 window.f1 && console.log('f1存在')
fn && fn()
fn存在就调用fn,不存在就不调用
|| 短路逻辑
A || B || C || D 取第一个真值或D,并不会取true或false
举例:
a||b //等同于 if(!a){ b }else{a} //如果a不存在,就执行b,否则还是a
a = a||100 //如果a存在就是a,如果a不存在就令a为100 //如果变量a存在,变量a就为第一个真值,再把变量a赋值给变量a,a还是a自己 //a不存在,那么第一个a不是真值,就执行最后一句a=100。给a一个保底值。 等同于 if(a){ a=a } else{ a=100 // 保底值 } //如果a不存在就令a为100,如果a存在就令a还是为a 等同于 if(!a){ a=100 // 保底值 } else{ a=a }
循环语句
while(不推荐)
1.基本结构
while (表达式) {循环体语句}
2.规则:
- 判断表达式的真假
- 当表达式为真,执行语句,执行完再判断表达式的真假
- 当表达式为假,执行后面的语句
注意:
容易死循环 (下面的代码将循环100次,直到i等于100为止)
var i = 0; //初始化表达式 while (i < 100) { //判断表达式 console.log('i 当前为:' + i); //循环体语句 i = i + 1; //递增表达式 }
浮点数不精确 (会进入死循环。因为浮点数a永远不会等于1)
while(a !== 1){ console.log(a) a=a+0.1 }
for循环
1.基本结构
for (初始化表达式; 判断表达式; 递增表达式) { 循环体语句 }
2.规则
- 先执行初始化表达式
- 再判断表达式的真假
- 如果为真,就执行循环体语句,然后执行递增表达式
- 如果为假,就直接退出循环,执行后边的语句
举例:
var x = 3; for (var i = 0; i < x; i++) { console.log(i); } // 0 // 1 // 2 // 最后循环执行完i=3
上面面代码中,初始化表达式是var i = 0,即初始化一个变量i;判断表达式是i < x,即只要i小于x,就会执行循环;递增表达式是i++,即每次循环结束后,i增大1。
for(var i=0;i<3;i++){ setTimeout(()=>{ console.log(i) },0) } //3个3 /* i=0满足i<3,所以执行循环体打出i,但要过一会。 以此类推 i=1满足i<3,所以执行循环体打出i,但要过一会。 i=2满足i<3,所以执行循环体打出i,但要过一会。 i=3不满足i<3,结束循环。 for循环不结束,就不算过一会! 现在循环结束了,过一会了,终于要打出i了,而且还要打出三次,因为此时i=3了。所以打出了3个3 */
所有for循环,都可以改写成while循环
var x = 3; var i = 0; while (i < x) { console.log(i); i++; }
break和continue
break语句和continue语句都具有跳转作用,可以让代码不按既有的顺序执行。
break语句用于跳出代码块或循环。
var i = 0; while(i < 100) { console.log('i 当前为:' + i); i++; if (i === 10) break; } //上面代码只会执行10次循环,一旦i等于10,就会跳出循环。
for循环也可以使用break语句跳出循环。
for (var i = 0; i < 5; i++) { console.log(i); if (i === 3) break; } // 0 // 1 // 2 // 3 //上面代码执行到i等于3,就会跳出循环。
continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。
var i = 0; while (i < 100){ i++; if (i % 2 === 0) continue; console.log('i 当前为:' + i); } //上面代码只有在i为奇数时,才会输出i的值。如果i为偶数,则直接进入下一轮循环。
如果存在多重循环,不带参数的break语句和continue语句都只针对最内层循环。
label
JavaScript 语言允许,语句的前面有标签(label),相当于定位符,用于跳转到程序的任意位置,标签的格式如下。
label: 语句
举例:
foo:{ console.log(1); break foo; console.log('本行不会输出'); } //foo是一个标签,表示一个代码块 //1
{ foo:1; } //这是一个代码块,代码块里有一个标签foo,标签foo的内容是1