1.JavaScript变量
变量(Variables)在程序中用于存储数据,我们可以将数据存入变量,并在将来替换变量中保存的数据,或是销毁变量。
在js中,使用var
关键字来声明变量(//
是单行注释符号,//
之后的在同一行的内容不会被运行,此外/* */
符号表示块注释,用于注释多行代码):
var a; // 声明变量a,此时变量的值为undefined
var b, c; // 声明变量b和变量c,这两个变量的值都为undefined
var d = 0; // 声明变量d,并将d赋值为0
var e, f = 1; // 声明变量e和f,其中e的值为undefined,f的值为1
分号作为js表达式的分隔符,是可以省略的,一般不推荐省略
变量的赋值
使用如下方法为变量赋值(存入或替换数据):
var a = 0; // 声明变量a并赋值为0
a = 1; // 将变量a重新赋值为1
let和const关键字
在ES6标准中,新增了let
和const
关键字,let
的语法与var
一致,但使用let
声明的变量,只在let
命令所在的块中有效,我们把这个有效区域称为块作用域:
{
let a = 0;
var b = 0;
a // a is 0
b // b is 0
}
a // a is undefined
b // b is 0
let
命令也不允许在同一个作用域内重复声明:
let a = 0;
let a = 1; // error
let b = 1; // correct
{
let a = 2; // correct
let a = 3; // error
}
const
关键字用于声明一个常量,一旦常量被声明,常量中存储的数据就不可以被修改。我们可以把常量理解为一个不允许修改内容的变量:
const a = 0;
a = 1 // error
使用const
关键字声明常量,必须在声明时给常量赋值:
const a; // error
变量命名规则
js中的变量有严格的命名规则:
- 变量名不允许以数字开头,但数字可以被用在变量中,例如:
3xxx
,12xxx
,这些是错误的变量名称,a1
,a2b
,这些是正确的名称; -
数学或者逻辑操作符(运算符)不允许出现在变量名中,例如:
a-b
,a|b
,a*b
,这些是错误的; - 除了下划线,任何标点符号都不允许出现在变量名中,例如:
a:b
,a#b
是错误的,a_b
,_ab
是正确的; - 空格不允许使用,变量名中不允许换行;
-
保留字和关键字不允许用作变量名,例如:
class
,string
是错误的,klass
,str
是正确的; - 变量名是大小写敏感的,例如:
a
与A
是两个截然不同的变量;
💡 实际上,符合js标识符规则的unicode字符都可以作为标识符,基于上述规则,我们应该可以知道,>
以下变量名都是合法的:$hello
,hello$
,你好
,ಠ_ಠ
,巴扎嘿123
。
⚠️ 实际使用中,不建议将中文字符和特殊符号作为变量名使用。
命名规范
js变量名应该语义化,即根据功能来命名,看到变量名称,基本就可以猜到变量的用途,常用的命名规范有三种:
👍 驼峰命名法:
这是js中最普遍使用的命名规范,驼峰命名法分为两种:
- 小驼峰命名法
用多个单词书写变量名时,首词的首字母小写,后面所有单词的首字母大写,例:doLogin
,setFirstName
。 - 大驼峰命名法
用多个单词书写变量名时,所有单词的首字母全部大写,这种命名方式常用在js的构造函数中,例:UserInfo
,SafeCenter
匈牙利命名法:
变量名 = 数据类型 + 描述
例如:
let sName = "HanMeiMei"; // s表示字符串类型string
let iPrice = 100; // i表示整型数字类型number(int)
帕斯卡命名法:
这种命名法即大驼峰命名法。
其他:
有些程序中推荐使用-
或者_
符号连接单词,例如:first-name
,delete_article
,这种命名法常用在c/c++程序中。
2.JavaScript数据类型
动态类型与弱类型
js是一种动态类型、弱类型的脚本语言。
在声明变量时,不需要为变量指定类型,js将会自动给变量指定类型,我们也可以将另一种类型的值直接赋值给已有的变量,这种类型被称为动态类型:
let a = 0 // 此时变量a保存的值是数字类型
a = "hello" // 允许直接将字符串类型的值赋值给变量a
在使用变量运算时,程序能够“容忍”类型的隐式自动转换,这种特性被称为弱类型:
let a = "hello"; // a是字符串string类型
let b = 1; // b是数字number类型
let c = a + b; // 结果为"hello1",js自动将加号左边的数字转换为字符串进行运算,结果为两个字符串的拼接
原始类型与对象类型
js中的数据类型可以概括为以下几种:
- 6种原始类型(原始类型也称为基本类型)
- Number 数字型
- String 字符串型
- Boolean 布尔型
- Undefind 未声明(转为数字时为NaN)
- Null 空值(转为数字时为0)
- Symbol 符号类型
- 1种对象类型
- Object 对象
Number类型
js的数字类型不区分精度,它只有一种类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(2^63 -1) 到 2^63 -1),js也没有为整数规定一种特殊类型。
除了整数、浮点数(小数)外,还有一些其他的数字:+Infinity正无穷大
,-Infinity负无穷大
,NaN (not a number 非数值)
拓展:
在ES6标准中,允许使用Number.MAX_SAFE_INTEGER
方法检查数字是否在允许的范围内
在ES6中,也可以用Number.MAX_SAFE_INTEGER
和Number.MIN_SAFE_INTEGER
表示js能够表示的最大和最小数字
js中,用+number
表示正数,+
符号可以省略,例如:+5
,5
;
用-number
表示负数,例如:-5
;
0也可以用-0
或者+0
表示,如果用一个数字除以0,将会得到无穷大:
12 / -0 = -Infinity
12 / +0 = +Infinity
将数字赋值给变量:
let a = 12;
let b = 3.14;
let c = -1;
String类型
字符串类型用于表示文本。js的字符串用单引号或者双引号表示:
let a = 'hello world';
let b = '123'; // 这里的'123'是一个字符串,它不能直接做四则运算
字符串的长度是指字符串中字符的个数,用string.length
来表示一个字符串的长度:
let str = 'hello world!';
console.log(str.length); // 12
拓展:浏览器控制台中调试时,如需查看变量,不需要输入
console.log
命令,直接输入变量名后回车即可
使用字符串时,一定要注意为字符串加上引号,变量和字符串的显著区别,在于变量没有引号,而字符串有引号!
Boolean 布尔型
布尔型表示逻辑中的正反两个方面,布尔类型有两个值:true
和false
。
Undefined
如果定义了一个变量但没有给它赋值,那么它的值是undefined
,注意区分大小写。
拓展1:一个函数如果没有返回值,那么它将返回undefined
拓展2:在局部作用域中,undefined允许被用作变量名,但是永远不要这样做
Null
空类型的值只能是null
,表示一个东西就是“空”这个状态,注意区分大小写:
let box = null // 空值,盒子里什么也没有,是空的
let bag;
console.log(bag) // undefined, bag被定义而没有赋值
Symbol类型*
Symbol类型用于表示一个独一无二的值,Symbol类型一般用作对象的属性名:
let sym1 = Symbol('a');
let sym2 = Symbol('a');
console.log(sym1 == sym2) // false,比较两个symbol的值,得到false
Object
对象类型较为复杂,在以后的教程中会逐一详细介绍。
js的对象有属性和方法两种成员,对对象的属性进行查看、修改等操作,称为对属性的访问,使用对象的方法,称为对方法的执行或调用,用点号.
来访问属性和执行方法:
语法:
Object.property // 访问属性
Object.function() // 调用方法
例:
/* 用花括号来表示一个对象,属性和方法可以自行规定,成员(属性和方法)之间用逗号做分隔 */
let 对象名(变量名) = {
属性1: 属性值,
属性2: 属性值,
方法名() {
方法体;
}
};
let student = { // 定义student对象
name: '小明', // student对象的name属性,值为字符串“小明”
age: 18, // student对象的age属性,值为数字18
// student对象的goToKlass方法,执行方法会在控制台输出字符串,class是js的保留字,为了避免误用做标识符,常将class写作klass
goToKlass() {
console.log('去上课');
}
};
console.log(student.name); // "小明",打印(访问)name属性
student.age = 20; // 修改age属性
console.log(student.age); // 20
student.goToKlass(); // "去上课",调用goToKlass方法
js中一切皆对象,这句话不是指一切都是对象类型,而是处理数据时可以把数据看作对象,js会自动为一些内容添加属性和方法,例如:
let name = 'xiaoming';
let r1 = name.length;
console.log(r1) // 8, 字符串有length属性,表示字符串的长度
let price = 6.9855;
let r2 = price.toFixed(2);
console.log(r2); // 字符串"6.99", Number.toFixed(n)方法将数字转换为字符串,并四舍五入保留n位小数
拓展:访问字符串的属性时,js临时创建一个对象,临时对象的属性只可读,不可写,访问结束后,临时对象即被销毁,这让字符串或数字类型的数据看起来也像一个对象,因此“一切皆对象”。
3.类型判断
typeof操作符
使用typeof
操作符来判断数据类型,这个运算返回一个表示类型的字符串:
let a = 'hello';
typeof a; // 'string'
typeof 321; // 'number'
typeof(321); // 'nunber'
typeof undefined; // 'undefined'
typeof {a: 1}; // 'object'
特殊情况
有些时候,typeof
判断出的类型不能“想当然”,以下例子中没有出现过的形式,在后面的课程中会介绍:
typeof null; // 'object'
typeof function( ){ } // 'function',即便函数属于对象类型,typeof会返回'function'
let str = new String('hello');
let num = new Number(123);
typeof str; // 'object'
typeof num; // 'object',new关键字实例化(可以理解为创建)一个对象
补充:正则表达式的类型在浏览器中使用
typeof
检测时有时是function
,有时是object
,这取决于运行js的浏览器,即js的宿主,在当前(2017.9)最新版本的chrome和firefox浏览器中,正则表达式的类型均为object
4. 运算操作符
n元操作符
n表示有n个操作数参与运算操作,js中有一元操作符和二元操作符,还有一个特殊三元操作符。
一元操作符: 操作符 操作数1 |或| 操作数 操作符
二元操作符: 操作数1 操作符 操作数2
三元操作符: 操作数1 操作符 操作数2 操作符 操作数3
算数运算符
算数运算符有加减乘除四则运算、求余、自增自减和-
、+
,下表的=
符号不表示赋值:
表达式 | 示例 | 说明 |
---|---|---|
a + b |
1 + 2 = 3 | 加法 |
a - b |
1 - 2 = -1 | 减法 |
a * b |
3 * 7 = 21 | 乘法 |
a / b |
6 / 2 = 3 | 除法 |
a % b |
5 % 2 = 1 | 求余 |
a++ ,++ a |
5++ = 6 | 自增 |
a-- ,-- a |
5-- = 4 | 自减 |
- a |
-5 = -5 | 取反 |
+ a |
+'8' = 8 | 将非数字转换为数字 |
++
和--
操作符
当把操作符放在前面时,返回加1后的操作数,例如:let a = 1; console.log(++a);
,结果为2,a在运算结束后也为2
当把操作符放在后面时,先返回原操作数,然后再将操作数加1:let a = 1; console.log(a++);
,结果为1,a在运算结束后值为2
+
操作符
+
操作符不仅仅表示数学运算的相加,当把+
操作符用在字符串中时,表示两个字符串的连接:
'hello' + 'world'
结果为 'helloworld'
赋值运算符
赋值运算符将右边的操作数赋值给左边的操作数,最常用的赋值运算符是等于=
符号,也有一些复合型的赋值运算符:
x = y // 把y的值赋值给x
x += y // 相当于 x = x + y('='符号的运算优先级很低,放在后面计算)
x -= y // x = x - y(注意x与y的顺序)
x /= y // x = x / y
x %= y // x = x % y
// 这里只列举常用的表达式,不包含完整的赋值运算操作符
比较运算符
比较运算符用于逻辑比较,返回true
或false
:
表达式 | 示例 | 说明 |
---|---|---|
a == b |
1 == 2 | false,等于时返回true |
a != b |
1 != 2 | true,不等于时返回true |
a === b |
1 === '1' | false,全等于,数值和类型都相等时返回true |
a !== b |
6 !== 2 | true,不全等于,数值或类型不等时返回true |
a > b |
5 > 2 | true,左侧大于右侧时返回true |
a < b |
5 < 6 | true,左侧小于右侧时返回true |
a <= b |
5 <= 4 | false,左侧小于等于右侧时返回true |
a >= b |
-5 >= -5 | true,左侧大于等于右侧时返回true |
逻辑运算符
与、或、非运算,是最常见的逻辑运算,当操作数都是布尔值时,逻辑运算的返回值也是布尔值,当逻辑运算符不是布尔值时,可能返回其他类型的值(示例中提到的转换,在本篇教程的后续部分会讲到):
表达式 | 示例 | 说明 |
---|---|---|
a && b |
exp1 && exp2 | 逻辑与,如果exp1能被转换为false,则返回exp1,否则返回exp2;两边都是true时,返回true,否则返回false |
a || b |
exp1 || exp2 | 逻辑或,如果exp1能被转换为true,则返回exp2,否则返回exp1;两边只要有任意一个是true时,返回true,否则返回false |
! a |
!exp | 逻辑非,如果exp能被转换为true,则返回false,否则返回true(逻辑取反) |
在js中,
null
,0
,""(空字符串)
,NaN
和undefined
能够被转换为false,简单地记忆为“非零非空即是true”
拓展:逻辑短路
上述的逻辑与和逻辑或有短路的特性,即:无论运算是否完全结束,如果当前的运算足够得出最终的结果时,则后续的运算立刻停止,并立刻返回最终结果,例:let x = 5; (x > 0) || (x++); //这里返回true console.log(x); // x为5,不为6
由于
x>0
已经足够得出true
这个结果,因此右边的表达式并没有运算。
- 逻辑与运算可以简单记忆为:两端都为true时返回true,否则返回false;
- 逻辑或运算可以简单记忆为:有任意一端为true时返回true,两端都为false时返回false。
以下是一些逻辑运算示例:
true && true // true
true || false // true
3 && 2 // 2
0 && 2 // 0
'' && 2 // '',引号内不写内容,表示空字符串
6 || 5 // 6
0 || 6 // 6
5 > 0 || 5 < 0 // true
false || 5 // 5
true && 3 // 3
!'hello' // false
移位运算符
表达式 | 示例 | 说明 |
---|---|---|
a << n |
8 << 1 | 16,左移位,8的二进制是1000,左移1位变为10000,换算为十进制得16 |
a >> n |
9 >> 2 | 2,右移位,9的二进制是1001,右移2位为10(多余位舍弃),换算为十进制得2 |
a >>> n |
8 >>> 2 | 2,补零右移,这个运算会将左边空缺的位置用0补齐,8的二进制是1000,补零右移两位是0010,换算为十进制得2 |
对于非小数来说,a << n
的左移运算相当于a*2^n
;
相应的,a >> m
的右移运算相当于a*2^-m
。
位逻辑运算符
表达式 | 示例 | 说明 |
---|---|---|
a & b |
3 & 2 | 2,按位与,在a与b的位表示中,每个对应的位都为1时返回1,否则返回0 |
a | b |
5 | 6 | 7,按位或,在a与b的位表示中,每个对应的位只要有一个为1,就返回1,否则返回0 |
~ a |
~3 | -4,按位非,对操作数的各个位取反 |
以计算5 | 6
为例,先将操作数转换为32位的整数,如果位数不够,则取低32位(低位指从右往左数32位),然后再将对应位两两比较:
5:0000 0000 0000 0000, 0000 0000 0000 0101
6:0000 0000 0000 0000, 0000 0000 0000 0110
r: 0000 0000 0000 0000, 0000 0000 0000 0111
因此最终结果为7
对于~3
这个表达式,由于按位非将所有位全部取反,左侧第一位表示符号位,当第一位是1时表示负数,因此最终结果为-4(二进制计算的结果是负数的补码表示法)
提示:位运算的运算效率比其他运算更高
条件运算符(三元)
语法:
条件?
值1:
值2
如果条件为true
,则运算结果取值1,否则取值2,值1和值2也可以是表达式,例:
let group = (age > 16) ? 'children' : 'young'; //当年龄大于16时,group的值为'young',否则为'children'
5.运算时的类型转换
字符串转数字
parseInt()
和parseFloat()
方法分别将字符串转换为整数和浮点数,这两个方法返回一个新的值,而不是修改被转换的值:
parseInt('3.14'); // 3,字符串转换为整数
parseFloat('3.14'); // 3.14,字符串转换为浮点数
parseInt('1f', 16); // 31,后面的16表示十六进制(以16为基数),运算结果为十进制16+15=31
自动类型转换
将不同的类型做运算时,js会临时将数值进行类型转换,以下列举部分转换规则:
-
字符串与数字相加,数字转型为字符串:
'hello' + 123 // 'hello123'
-
布尔与数字相加,布尔转型为数字,true对应1,false对应0:
true + 1 // 2
-
布尔与字符串相加,布尔转型为字符串:
true + hello // 'truehello'
扩展:快速转换字符串和数字
字符串转数字:+String
,在字符串前添加+
符号可以快速将字符串转换为数字
数字转字符串:'' + Number
或Number + ''
,数字加空字符串可以得到一个与数字值相等的字符串
6.运算符优先级
四则运算中,乘除法比加减法的优先级更高(与我们的常识相同),连续做加法时,从左往右计算,千万不可以随意使用数学中的结合律运算:
'hello' + 1 + 2 // 结果为'hello12',不能先计算后面的1+2
运算符的优先级从高到低如下所示,高优先级的符号优先计算:
- 圆括号
- 后置自增自减(a++)
- 逻辑非, 按位非
- 一元加减法(+a, -b),前置自增自减,typeof
- 乘除法,求余
- 加减法
- 移位
- 大小比较,大于等于,小于等于
- 等于,全等于,不等于,不全等于
- 按位与
- 按位或
- 逻辑与
- 逻辑或
- 条件运算
- 赋值运算
- 逗号
本系列教程作品采用 [知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议] 进行许可。 转载请发邮件到我的邮箱340349237@qq.com,并注明作者Tianzhen。
练习:Day1.5:巩固练习
下一篇:Day2:字符串与数组