JavaScript语法
JS版本
历史版本
- ES3,IE6支持
- ES 5,过时了
- ES6,大部分浏览器支持,总体 一部分垃圾,一部分好
- ES2019与 ES6差别不大
为什么ES6 一部分是垃圾
- ES 不能删除以前的特效,要兼容旧网站
- 也就是以前能运行的网站,以后都要能运行
- 对比Python 3 就能知道兼容的好处:稳定
在学习JS的时候,取其精华,去其糟粕。
JS之父对JS的评价:它的优秀之处并非原创,它的原创之处并不优秀。
表达式与语句
表达式
- 1 + 2 表达式的值为3
- add(1,2) 表达式的值为函数的返回值
- console.log表达式的值为函数本身
- console.log(3) 表达式的值是undefined
语句
- var a = 1 就是一个语句
二者的区别
- 表达式一般都有值,语句可能有也可能没有
- 语句一般会改变环境(声明、赋值)
- 但不是绝对的
大小写敏感
不要写错
- var a 和 var A 是不同的
- object 和 Object是不同的
- function 和 Function 是不同的
空格
大部分空格没有实际意义
- var a = 1 和 var a=1 没有区别
- 加回车大部分时候也不影响
- 只有一个地方不能加回车,那就是return后面
标识符
规则
- 第一个字符,可以是Unicode 字母或$或者_或中文
- 后面的字符,除了上面所说,还可以有数字
变量名是标识符
- var _ = 1
- var $ = 2
- var ____ = 6
- var 你好 = 'hi'
还有一些其他的标识符。
错误的命名
var 9$
Uncaught SyntaxError: Invalid or unexpected token
注释
写代码的时候要加注释
单行注释://
多行注释:/**/
注释的分类
不好的注释
- 把代码翻译成中文
- 过时的注释
- 发泄不满的注释
好的注释
- 踩坑的注释
- 为什么代码会写的这么奇怪,遇到什么bug
区块block
把代码包在一起
{
let a = 1
let b = 2
}
常常与if 、for 、while 一起使用
if语句
语法
- if(表达式) {语句1} else {语句2}
- {} 在语句只有一句的时候可以省略,但不建议这么做
变态情况
- 表达式里可以非常变态,如 a = 1
- 语句1 语句2 也有很复杂的情况,如嵌套的 if else
- 缩进也可以很变态,面试题常常下套
a = 1
if(a === 2)
console.log('a')
console.log('a等于2')
使用最没有歧义的写法
if(表达式){
}else if (表达式){
}else
次推荐的写法
function fn(){
if(表达式){
return 表达式
}
if(表达式){
return 表达式
}
if(表达式){
return 表达式
}
}
Switch语句(if..else..升级版)
语法
switch(fruit){
case "banana":
//...
break;
case "apple":
//...
break;
default:
//...
}
break
- 大部分时候不能省略break
- 少部分时候可以利用break特性
问号冒号表达式(三元表达式)
表达式1?表达式2:表达式3
&&短路逻辑
A && B && C && D 取第一个假值或D,并不会取true/false。window.f1 && console.log('f1存在')
|| 短路逻辑
A || B || C || D 取第一个真值,或者D,并不会取true/false,而是ABCD中的一个
总结
条件语句
- if ... else...
- switch
- A ? B : C
- A && B
- fn && fn()
- A || B
- A = A || B
while 循环
语法
- while (表达式) {语句}
- 判断表达式的真假
- 当表达式为真,执行语句
- 当表达式为假,执行后面的语句
- 执行完再次判断表达式的真假
其他
- do...while 循环语句至少执行依次,用的很少。
for循环
语法糖
- for是while循环的方便写法
语法
for(初始化语句1;表达式2;语句3){
循环体
}
- 先执行语句1
- 如何判断表达式2
- 如果为真,执行循环体,如何执行语句3
- 如果为假,直接退出循环,执行后面的语句
break 和 continue
退出当前的for循环V.S. 退出当前本次循环
label语句
语法
foo: {
console.log(1);
break foo;
console.log('本行不会输出');
}
console.log(2);
面试可能会问这东西是什么?
{
foo: 1
}
数据类型
数据为什么需要类型
数字与字符串
都是一,为什么要分 1 和 '1'
功能不同
- 数字是数字,字符串是字符串,要严谨
- 数字能加减乘除,字符串不行
- 字符串能表示电话号码,数字不行
存储形式不同
- JS 中,数字是用64位浮点数的形式存储的
- JS中,字符串使用类似UTF8形式存储的(UCS-2)
ASCII码:48=0 65=A 97=a
JS中的数据类型
七种(大小写无所谓)
- 数字 number
- 字符串 string
- 布尔 bool
- 符号 symbol
- 空 undefined
- 空 null
- 对象 object
- bigint(2020年新增类型)
- 总结:四基本两空一对象
以下不是数据类型
- 数组、函数、日期
- 它们都属于object
数字number
number在js中由64位浮点数组成
写法
- 整数写法:1
- 小数写法:0.1
- 科学计数法:1.23e4
- 八进制学法(用得少):0123 或 00123 或 0o123
- 十六进制写法:0x3F 或 0X3F
- 二进制写法:0b11 或者 0B11
特殊值
- 正 0 和 负 0:都等于0,要严谨
- 无穷大:Infinity、+Infinity、-Infinity
- 无法表示的数字:NaN(Not a Number),但是它是一个数字
64位浮点数
JS数学的存储形式
- 浮点就是浮动的点,意思就是小数点会乱动
- 123.456 也可以表示位 1.23456e102,还可以表示为 12345.6e10-2
64位存储一个 number
- 符号占一位
- 指数占11位(-1023~1024)
- 有效数学占 52 位(开头的 1 省略)
范围和精度
范围(忽略符号位)
- 指数拉满,有效数字拉满,得到最大二进制数字
- Number.MAX_VALUE: 1.7976931348623157e+308
- 指数负方向拉满、有效数字最小1,得到最小值
- Number.MIN_VALUE:5e-324
精度(有效数字)
- 最多只能到52+1个二进制位表示有效数字
- 2^53对应的十进制是9后面15个零
- 所以15位有效数字都能精确表示
- 16位有效数字如果小于90开头,也能精确表示,但是如果是9110000000000001 就存不下来了
字符串String
每个字符两个字节(阉割版UTF8)
写法
- 单引号:'你好'
- 双引号:"你好"
- 反引号:
你好
- 注意:引号不属于字符串的一部分,就像书名号不属于书名的一部分一样
- 如果要在单引号里面包含单引号怎么办?
转义
用另一种写法表示你想要的东西
- 错误写法:'it's ok' JS引擎会认为'it'就结束了,后面的看不懂
- 正确写法:'it's ok' //这就是转义 "it's ok"
it's ok
- \n 表示换行、\r 表示回车、\t 表示tab制表符、\ 表示 \、\uFFFF 表示对应的Unicode字符、\xFF 表示前 256个 Unicode 字符
多行字符串
如果你想要在字符串里回车
let s = `这样是
可以的
使用反引号就可以做到
`
string.length //可获取字符串的长度
'\n\t\r'.length //长度是3
通过下标读取字符
- string[index],注意index从0开始,注意index 到 length。
base64编码
加密:window.btoa("123"),解码:window.atob("MTIz")
- window.btoa ,正常字符串转为base64编码的字符串
- window.atob, Base64编码的字符串转为原来的字符串
- 一般用来隐藏招聘启事里面的邮箱:Nzg1ODc5OTg2QHFxLmNvbQ==
布尔boolean
下列运算符会得到bool值
- 否定运算:!value
- 相等运算:1==2、1 != 2、 3===4、3 !== 4
- 比较运算:1 > 2 、1 >= 2、3 < 4、 3 <=4
if 配 bool
- if语句常常需要判断真假:if(value) else
- 问题来了:如果value 是 bool 值还好说,如果value不是bool值咋办
- 1 是真还是假,0 是真还是假,'1' 是真还是假,'0'是真还是假
JS有五个 falsy 值,falsy 就是相当于 false但又不是false的值,分别是 undefined 、null 、0 、NaN 、''。
再加上false 就一共是六个假值
'' 和 ' ' 不是一个玩意,保持严谨
undefined 和 null 两种空类型
这是是JS的原创,也是垃圾的地方。
区别
- 没有本质区别
- 细节一:如果一个变量声明了,但是没有复制,那么默认值就是undefined,而不是null
- 细节二:如果一个函数,没有写return,那么默认return undefined,而不是null
- 细节三:前端程序员习惯上,把非对象的空值写为undefined,把对象的空值写为 null(但这只是习惯)
变量声明
三种声明方式
- var a = 1
- let a = 1
- const a = 1
- a = 1(错误的)
区别
- var 是过时的、不好用的方式
- let 是新的,更合理的方式
- const 是声明时必须赋值,且不能再改的方式
- 最后这种方式是错误的,不能这样声明
TODO:var 有个变量提升的概念
let声明
规则
- 遵循块作用域,使用范围不能超出{}
- 同一个{}中不能重复声明
- 可以赋值,也可以不赋值
- 必须先声明在使用,否则报错
- 全局声明的let变量,不会变成window 的属性
- for循环配合let 有奇效
const声明
规则:跟let几乎一样,声明时必须马上赋值,而且后续不能再改变这个值。
变量声明的同时指定了值,同时也指定了类型,但是值和类型都可以随意变化
let a = 1
a = 2
a = '字符串'
name 和 'name' 的区别:存的地方不一样,字符串存在stack区。name可以是任何类型,'name'确定是字符串
类型转换
number => string
- String(n) 或 n + ''
string => number
- Number(s)
- parseInt(s) / parseFloat(s)
- s - 0
x => bool
- Boolean(x)
- !!x (取反再取反,相当于原值)
x => string
- String(x)
- x.toString()
总结
六种类型:undefined、null、number、string、bool、symbol
这些都是简单类型,只有object叫做复杂类型