表达式与语句
表达式
- 1+2 表达式的值为 3
- add(1,2)表达式的值为函数的返回值
- console.log 表达式的值为函数本身
- console.log(3)表达式的值为多少?
语句
var a=1是一个语句
二者的区别
- 表达式一般都有值,语句可能有也可能没有
- 语句一般会改变环境(声明、赋值)
- 上面两句话并不是绝对的
大小写敏感,不要写错
- var a 和 var A 是不同的
- object 和 Object 是不同的
- function 和 Function 是不同的
- 具体含义后面会学习
关于空格和回车
- 只要不影响断句,大部分空格没有实际意义
- var a = 1 和 var a=1 没有区别
- 加回车大部分时候也不影响
- 只有一个地方不能加回车,那就是 return 后面,加了回车会自动隐性地补上 undefined,回车后面的值不会上来。这是面试喜欢考的一个点,面试不考常态只考变态。
标识符
规则
- 第一个字符,可以是 Unicode 字母或$或_或中文
- 注:Unicode 字母不只包含英文字母,还有希腊字母德语字母法语字母等,都可以用
- 后面的字符,除了上面所说,还可以有数字
变量名是标识符
var _=1var $=2var ______=6var 你好='hi'
其它标识符用到再说
注释——写代码要多写注释吗?不是这样的
注释的分类
不好的注释
- 把代码翻译成中文
- 过时的注释
- 发泄不满的注释
好的注释
- 踩坑注释。比如说你发现了一个 bug,把它解决了,解决的过程你觉得可能后面还会遇到,然后可能会忘掉,你就把这个解决的过程写到代码注释里面,‘我经过了什么什么搜索,搜到了这个方案,以后如果你遇到同样问题你也这样做’。
- 为什么代码会写得这么奇怪,遇到什么 bug。奇怪的原因是产品的需求就是特别奇怪,比如之前有个公司它故意把用户的操作延迟 10s,中间一直是加载中,就是为了收钱,如果你没有交钱,那么就等 10s 然后才发这个请求,如果你交了钱,马上发,那你就要在注释里面写清楚,这个代码是为了某个特性,但你不要写得太明确,免得被别人坑。有的时候公司要生存下来,它也不得不设置一些限制,比如说只能用一个月,一个月之后就收费,或者只能同时拥有三个用户,超过三个再收费,写注释的时候就要写,我为什么要故意延迟 10s 呢,是为了某个特性,把特性名字写下,可能就是个代号。或者你遇到一个 bug,为了解决这个 bug 不得不写一些非常奇怪的代码,那你就把这个 bug 遇到的现象也写到注释里面,这样后面的人在看你的代码的时候就不会轻易的改。
好的注释就是告诉你为什么这样写,烂的注释就是告诉你我写了什么,但是优秀的程序员不需要你告诉我写了什么,只要你把代码命名好我就知道你写了什么。
区块 block
把代码包在一起
{
let a=1
let b=2
}
block 一般不会单独用,一般是跟其它的东西一起用
常常与 if/for/while 合用
if 语句
语法
- if(表达式){语句 1}else{语句 2}
- {}在语句只有一句的时候可以省略,不建议这样做
变态情况
- 表达式里可以非常变态,如 a=1
- 语句 1 里可以非常变态,如嵌套的 if else
- 语句 2 里可以非常变态,如嵌套的 if else,还可以省掉花括号
- 缩进也可以很变态,如面试题常常下套:
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')
答案是,undefined。因为逗号表示这句话没完,这两个语句突然就变成了一个语句。分号的话,就表示这句话完了。
程序员第二戒律,永远使用最没有歧义的写法
(程序员第一戒律,永远不要相信人类,所有人类会做的事情都会出错)
最推荐使用的写法
if(表达式){
语句
}else if(表达式){
语句
}else{
语句
}
永远不要省略花括号,就算里面只有一句也不要省略花括号。
次推荐使用的写法
function fn(){
if(表达式){
return 表达式
}
if(表达式){
return 表达式
}
return 表达式
}
switch 语句 ,不推荐
- 大部分时候,省略 break 你就完了
- 少部分时候,可以利用 break
问号冒号表达式,有人称其为三元表达式
表达式 1?表达式 2:表达式 3
能用问号冒号的时候,就不要用 if else
function max(a,b){
if(a>b)return a;
else return b;
}
可以简化成如下代码
function max(a,b){
return a>b?a:b
}
&& 短路逻辑
A&&B&&C&&D取第一个假值或 D,并不会取 true/false
if(window.f1){
console.log('f1存在')
}
等价于
window.f1&&console.log('f1存在')
||短路逻辑
A||B||C||D取第一个真值或 D,并不会取 true/false
a||b
等价于:
if(!a){
b
}else{}
a=a||100
等价于:
if(a){
a=a
}else{
a=100//保底值
}
前端程序员如果能写成||,就绝对不写 if else
总结
条件语句
- if...else...
- switch
- A?B:C
- fn&&fn()
- A||B
- A=A||B
while 循环,当...时
语法
- while(表达式){语句}
- 判断表达式的真假
- 当表达式为真,执行语句,执行完再判断表达式的真假
- 当表达式为假,执行后面的语句
题目——死循环(考点)
while(true){}
var a=0.1//初始化
while(a!==1){//判断
console.log(a)//循环体
a=a+0.1//增长
}
上面是浮点数不精确造成的问题
其他
- do...while,用的不多
for 循环
- for 是 while 循环的方便写法,for 循环是 while 循环的升级写法
- while 循环有一个问题是,你如果缺了一部分就会死循环,比如说没有写初始化,死循环,没有写判断或者判断写错了,死循环,你没有写循环体,那你循环也没什么用,没有写增长,死循环
语法
for(语句 1;表达式 2;语句 3){ 循环体 }
- 先执行语句 1(语句 1 是用来初始化的)
- 然后判断表达式 2(表达式 2 是用来判断的)
- 如果为真,执行循环体,然后执行语句 3(语句 3 是自增用的)
- 如果为假,直接退出循环,执行后面的语句
- 注意:如果表达式 2 成立,先执行循环体,
再执行语句 3,注意这个再,这是考点。执行循环体后,一定会去执行语句 3,除非你有 break。
题目(考点。这个问题的考点不在于 for 循环,在于 setTimeout 的时间问题)
for(var i=0;i<5;i++){
setTimeout(()=>{
console.log(i)
},0)
}
问:最后打印出来的结果。
答:五个 i,因为 setTimeout 过一会时间才打印,等过一会,i 已经执行完了,所以,打印出五个 i。
var a=1
function fn(){
console.log(a)
}
问:打印出 a,a 的值是多少?
答:不确定。因为 a 现在等于 1,但不知道什么时候执行 fn。a 的值可能会变,如果不确定函数是什么时候执行的,永远不能确定 a 的值是多少。所以如果我不能确定 fn()的调用时间,我是不能说 a 的值的。
for(let i=0;i<5;i++){
setTimeout(()=>{console.log(i)})
}
上面这段代码打印出来依次是:0,1,2,3,4
问:为什么呢?
答;
break 和 continue
退出所有循环 V.S.退出当前一次循环
注意:break 只会退出离它最近的循环
label 语句
用的很少,面试会考(概率 5%)
语法
foo:{
console.log(1);
break foo;
console.log('本行不会输出');
}
console.log(2);
面试
{
foo:1
}
- 问:上面的东西是什么
- 答:foo 是一个 label,它的语句就是一个 1
推荐书籍
阮一峰的免费教程
《你不知道的 JavaScript》
- 先买上卷,适合进阶