基本语法
条件语句
JavaScript 提供if结构和switch结构,完成条件判断,即只有满足预设的条件,才会执行相应的语句。
if结构
1.规则
- 先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句。
- 所谓布尔值,指的是 JavaScript 的两个特殊值,true表示真,false表示伪。
- 如果表达式的求值结果为true,就执行紧跟在后面的语句;如果结果为false,则跳过紧跟在后面的语句。
2.基本形式
if (布尔值){
语句
}
// 或者
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部分。
注:
case代码块之中没有break语句,导致不会跳出switch结构,而会一直执行下去switch语句部分和case语句部分,都可以使用表达式。
问好冒号表达式(三元运算符 ?:)
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循环。上面的例子改为while循环
var x = 3;
for (var i = 0; i < x; i++) {
console.log(i);
}
// 0
// 1
// 2
上面代码中,初始化表达式是var i = 0,即初始化一个变量i;测试表达式是i < x,即只要i小于x,就会执行循环;递增表达式是i++,即每次循环结束后,i增大1
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
数据类型
数值(number)
数值的存储方式
JS中,数字是用64位浮点数的形式存储的。(二进制)
其中符号占1位,指数部分有11位,范围从-1023到+1024,有效数字有 52 位,需要省略开头的 1 。 例如:0.5的存储方式是 0|-1|0 。
浮点数的范围
(1)最大值
- 把指数部分11位和有效数字的52位全设为1(拉满),可得最大的二进制数字
- 换成十进制为 Number.MAX_VALUE: 1.7976931348623157e+308
(2)最小值
- 指数负方向拉满、有效数字最小1,得到最小的二进制数字
- 换成十进制为Number.MIN_VALUE: 5e-324
精度
- 最多只能到52+1个二进制位表示有效数字
- 2^53对应的十进制是9后面15个零
- 所以对于十进制来说15位数字都能精确表示
- 16位有效数字如果小于90开头,也能精确表示
- 91 10000000000001就存不下来
数值的表示法:
- 整数 1
- 小数 0.1
- 科学计数法 1.23e4 (e4就是乘以10的4次方)
- 八进制(用得少)0123,00123,0o123
- 十六进制 0x3F 0X3F (用得少)
- 二进制 0b11 或0B11 (用得少)
数值的进制
JavaScript 对整数提供四种进制的表示方法:十进制、十六进制、八进制、二进制
- 十进制:没有前导0的数值
- 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。如0123或00123或0o123
- 十六进制:有前缀0x或0X的数值。如0x3F或0X3F
- 二进制:有前缀0b或0B的数值。如0b11或0B11
特殊数值
- 正0 和 负0都等于 0, 但是是三个数
- 无穷大: Infinity 、+Infinity 、-Infinity
- 无法表示的数字:NaN(Not a Number),但他是一个数字 。(比如0除以0,返回NaN) NaN不等于任何值,包括NaN。
方法
toString() 以字符串返回数值。
parseInt方法用于将字符串转为整数。
parseFloat方法用于将一个字符串转为浮点数。
isNaN方法可以用来判断一个值是否为NaN
toExponential()返回字符串值,它包含已被四舍五入并使用指数计数法的数字。
isFinite方法返回一个布尔值,表示某个值是否为正常的数值
toFixed()返回字符串值,它包含了指定位数小数的数字:
var x = 9.656;
x.toFixed(0); // 返回 10
x.toFixed(2); // 返回 9.66
x.toFixed(4); // 返回 9.6560
x.toFixed(6); // 返回 9.656000
toPrecision()返回字符串值,它包含了指定长度的数字
var x = 9.656;
x.toPrecision(); // 返回 9.656
x.toPrecision(2); // 返回 9.7
x.toPrecision(4); // 返回 9.656
x.toPrecision(6); // 返回 9.65600
布尔(bool)
只有两个值,true和false 下列运算符会返回布尔值:
- 前置逻辑运算符:
! (Not) - 相等运算符:
===,!==,==,!= - 比较运算符:
>,>=,<,<=
如果 JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false,其他值都视为true
undefinednullfalse0NaN- ''(空字符串)
这五个 falsy 值代表假的。(还有false)
undefined和null
undefined 和 null 是两种空类型,区别如下:
- 声明变量但是没有赋值,默认值是undefined,不是null。
- 函数没有return,那么默认return undefined,而不是 null。
- 习惯上,非对象的空值写为undefined,把对象的空值写为 null。
字符串(string)
1、写法
- 单引号 'hi'
- 双引号 "hi"
- 反引号 ``
引号不属于字符串的一部分
2、转义
例如 'it's ok' ,JS引擎会认为 'it' 就结束了。
正确写法
- 转义: 前面加斜杠 \ ,例如 'it's ok'
- 外面用双引号:"it's ok"
- 外面用反引号
转义——用另一种写法表示你想要的东西
- ' —— ' 单引号
- " —— " 双引号
- \n —— 换行
- \r —— 回车
- \t —— tab 制表符
- \ —— \斜杠
- \uFFFF —— 对应的Unicode 字符
- \xFF —— 前 256 个Unicode 字符
- 多行字符串:外面用反引号
3、字符串长度
string.length —— 即可看见字符串string的长度 例如:'\n\r\t'.length //值为3
通过下标可以读取字符(类似数组) 例如:let s='hello';s[0] //值为"h"
4、base64转码
- window.btoa(字符串)—— 正常字符串转为Base64编码的字符串
- window.atob(字符串) —— Base64编码的字符串转为原来的字符串
-
五、symbol符号
三种声明方式
var a = 1是过时的、不好用的方式let a = 1是新的,更合理的方式const a = 1是声明时必须赋值,且不能再改的方式a = 1最后这种方式是错误的,不准这样声明
let声明
- 遵循块作用域,适用范围不能超过{}
- 不能重复声明
- 可以赋值,也可以不赋值
- 必须先声明再使用
- 全局声明的let变量,不会变成window属性
- for循环配合let 有奇效
const声明
- 跟let规则一样
- 只有一条不同,声明时就要赋值,赋值后不能改
注意:声明变量的同时,也指定了类型,但是值和类型都可以随时变化
类型转换
1、number => string
String(n)n+''''+n
2、string => number
Number(s)parseInt(s)parseFloat(s)s-0+s
3、x => bool
Boolean(x)!!x一个感叹号可把任何东西取反布尔值,再来一个就是反布尔值的反布尔值,也就是原始布尔值
4、X => string
String(x)x.toString()- 数字1不可用上面的,因为默认1.后面应是小数。bug!
(1).toString()1..toString()1 .toString()
对象
数组
待补充,贴一篇大佬的文 JS数组奇巧淫技 - 掘金 (juejin.cn)