Day1:JavaScript变量与类型

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标准中,新增了letconst关键字,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中的变量有严格的命名规则:

  1. 变量名不允许以数字开头,但数字可以被用在变量中,例如:3xxx12xxx,这些是错误的变量名称,a1a2b,这些是正确的名称;
  2. 数学或者逻辑操作符(运算符)不允许出现在变量名中,例如:a-ba|ba*b,这些是错误的;
  3. 除了下划线,任何标点符号都不允许出现在变量名中,例如:a:ba#b是错误的,a_b_ab是正确的;
  4. 空格不允许使用,变量名中不允许换行
  5. 保留字关键字不允许用作变量名,例如:classstring是错误的,klassstr是正确的;
  6. 变量名是大小写敏感的,例如:aA是两个截然不同的变量;

💡 实际上,符合js标识符规则的unicode字符都可以作为标识符,基于上述规则,我们应该可以知道,>
以下变量名都是合法的:$hellohello$你好ಠ_ಠ巴扎嘿123
⚠️ 实际使用中,不建议将中文字符特殊符号作为变量名使用。

命名规范

js变量名应该语义化,即根据功能来命名,看到变量名称,基本就可以猜到变量的用途,常用的命名规范有三种:
👍 驼峰命名法:
这是js中最普遍使用的命名规范,驼峰命名法分为两种:

  1. 小驼峰命名法
    用多个单词书写变量名时,首词的首字母小写,后面所有单词的首字母大写,例:doLoginsetFirstName
  2. 大驼峰命名法
    用多个单词书写变量名时,所有单词的首字母全部大写,这种命名方式常用在js的构造函数中,例:UserInfoSafeCenter

匈牙利命名法:
变量名 = 数据类型 + 描述
例如:

let sName = "HanMeiMei"; // s表示字符串类型string
let iPrice = 100; // i表示整型数字类型number(int)

帕斯卡命名法:
这种命名法即大驼峰命名法。


其他:
有些程序中推荐使用-或者_符号连接单词,例如:first-namedelete_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_INTEGERNumber.MIN_SAFE_INTEGER表示js能够表示的最大和最小数字

js中,用+number表示正数,+符号可以省略,例如:+55
-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 布尔型

布尔型表示逻辑中的正反两个方面,布尔类型有两个值:truefalse

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
// 这里只列举常用的表达式,不包含完整的赋值运算操作符

比较运算符

比较运算符用于逻辑比较,返回truefalse

表达式 示例 说明
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中null0""(空字符串)NaNundefined能够被转换为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,在字符串前添加+符号可以快速将字符串转换为数字
数字转字符串:'' + NumberNumber + '',数字加空字符串可以得到一个与数字值相等的字符串

6.运算符优先级

四则运算中,乘除法比加减法的优先级更高(与我们的常识相同),连续做加法时,从左往右计算,千万不可以随意使用数学中的结合律运算:

'hello' + 1 + 2 // 结果为'hello12',不能先计算后面的1+2

运算符的优先级从高到低如下所示,高优先级的符号优先计算:

  1. 圆括号
  2. 后置自增自减(a++)
  3. 逻辑非, 按位非
  4. 一元加减法(+a, -b),前置自增自减,typeof
  5. 乘除法,求余
  6. 加减法
  7. 移位
  8. 大小比较,大于等于,小于等于
  9. 等于,全等于,不等于,不全等于
  10. 按位与
  11. 按位或
  12. 逻辑与
  13. 逻辑或
  14. 条件运算
  15. 赋值运算
  16. 逗号

本系列教程作品采用 [知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议] 进行许可。 转载请发邮件到我的邮箱340349237@qq.com,并注明作者Tianzhen

练习:Day1.5:巩固练习
下一篇:Day2:字符串与数组

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容