1.简介
JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有八种,但我们先只学习其中常见的的六种
- 数值
number:整数和小数(比如1和3.14) - 字符串
string:文本(比如"Hello World"或'Hello World') - 布尔值
boolean:表示真伪的两个特殊值,即true(真)和false(假) undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值(该类型的值唯一并且为其本身)null:表示空值,即此处的值为空(该类型的值唯一并且为其本身)- 对象
object:各种键值对组成的集合(此处指广义的对象)
// 函数返回”function” function f() {} typeof f // “function”
// undefined返回”undefined” typeof undefined // “undefined”
// 对象返回”object”({}为狭义对象的声明方式之一,[]为数组的声明方式之一) typeof {} // “object” typeof [] // “object”
```javascripttypeof null // "object"
null的类型是object,这是由于历史原因造成的。1995年的 JavaScript 语言第一版,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),没考虑null,只把它当作object的一种特殊值。后来null独立出来,作为一种单独的数据类型,为了兼容以前的代码,typeof null返回object就没法改变了
3.数值
3.1数值的表示方法
// 可以使用科学表示法123000 === 123e3 // true0.123 === 123e-3 // true// 表示小数时可省略00.123 === .123 // true
3.2数值的进制
使用字面量(literal)直接表示一个数值时,JavaScript 对整数提供四种进制的表示方法:十进制、十六进制、八进制、二进制。
- 十进制:没有前导0的数值。
- 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。
- 十六进制:有前缀0x或0X的数值。
- 二进制:有前缀0b或0B的数值。
默认情况下,JavaScript 内部会自动将八进制、十六进制、二进制转为十进制。下面是一些例子。
0xff // 2550o377 // 2550b11 // 3
如果八进制、十六进制、二进制的数值里面,出现不属于该进制的数字,就会报错
0xzz // 报错0o88 // 报错0b22 // 报错
3.3NaN
NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合
5 - 'x' // NaN
需要注意的是,NaN不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number,使用typeof运算符可以看得很清楚
typeof NaN // 'number'
4.字符串
4.1字符串书写方式
字符串就是零个或多个排在一起的字符,放在单引号或双引号之中
'abc'"abc"
单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号
'key = "value"'"It's a long journey"
字符串默认只能写在一行内,分成多行将会报错
'abc'// SyntaxError: Unexpected token ILLEGAL
如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠或连接运算符+
'Long \long \long \string''Long '+ 'long '+ 'long '+ 'string'
4.2字符串遍历方式
var str='我是一个字符串';// 读取方式(字符串与数组类似,可通过索引读取)str[0] // '我'str.length // 7// 遍历方式for(var i=0; i<str.length; i++){console.log(str[i]);}
5.对象
5.1对象生成方法
对象(object)是 JavaScript 语言的核心概念,也是最重要的数据类型
什么是对象?简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合
var obj = {foo: 'Hello',bar: 'World'};
上面代码中,大括号就定义了一个对象,它被赋值给变量obj,所以变量obj就指向一个对象。该对象内部包含两个键值对(又称为两个“成员”),第一个键值对是foo: 'Hello',其中foo是“键名”(成员的名称),字符串Hello是“键值”(成员的值)。键名与键值之间用冒号分隔。第二个键值对是bar: 'World',bar是键名,World是键值。两个键值对之间用逗号分隔
5.2对象属性的增删改查(新增、删除、修改、查询)
var obj = {foo: 'Hello',bar: 'World'};// 两种查询方式obj.foo // 'Hello'obj['bar'] // 'World'// 通过赋值语句进行新增和修改obj.a='你好';obj.bar='世界';obj.bar // '世界'// delete删除命令delete obj.barobj.bar // undefined
5.3对象的引用
var o1 = {};var o2 = o1;o1.a = 1;o2.a // 1o2.b = 2;o1.b // 2
上面代码中,o1和o2指向同一个对象,因此为其中任何一个变量添加属性,另一个变量都可以读写该属性。
此时,如果取消某一个变量对于原对象的引用,不会影响到另一个变量
var o1 = {};var o2 = o1;o1 = 1;o2 // {}
但是,这种引用只局限于对象,如果两个变量指向同一个原始类型的值。那么,变量这时都是值的拷贝
var x = 1;var y = x;x = 2;y // 1
上面的代码中,当x的值发生变化后,y的值并不变,这就表示y和x并不是指向同一个内存地址
5.4对象属性的遍历
var obj = {foo: 'Hello',bar: 'World'};// 方式一:通过Object.keys(obj)获取所有键名数组,然后遍历数组来访问对象属性var keys = Object.keys(obj)keys // ['foo','bar']for(var i=0; i<keys.length; i++){console.log(obj[ keys[i] ]);}// 方式二:for...in循环for(var key in obj){console.log('键名',key);console.log('键值',obj[key]);}
6.数组
6.1数组生成方法
数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示
var arr=['a','b','c'];
上面代码中的'a'、'b'、'c'就构成一个数组,两端的方括号是数组的标志。'a'是0号位置,'b'是1号位置,'c'是2号位置
除了在定义时赋值,数组也可以先定义后赋值
var arr=[];arr[0] = 'a';arr[1] = 'b';arr[2] = 'c';
6.2数组的本质
typeof [1, 2, 3] // "object"
上面代码表明,typeof运算符认为数组的类型就是对象。
数组的特殊性体现在,它的键名是按次序排列的一组整数(0,1,2…)。
var arr = ['a', 'b', 'c'];Object.keys(arr)// ["0", "1", "2"]
6.3length属性
数组的length属性,返回数组的成员数量
['a', 'b', 'c'].length // 3
6.4数组的遍历方式
var arr=[1,2,3];// 方式一:通过length确定长度,使用循环依次读取for(var i=0; i<arr.length; i++){console.log(arr[i]);}// 方式二:for...in循环for(var i in arr){console.log(arr[i]);}
7.函数
7.1函数的声明
function命令
function命令声明的代码区块,就是一个函数。function命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函数体放在大括号里面
function print(s) {console.log(s);}
- 函数表达式
除了用function命令声明函数,还可以采用变量赋值的写法
var print = function(s) {console.log(s);};
Function构造函数
第三种声明函数的方式是Function构造函数
var add = new Function('x','y','return x + y');// 等同于function add(x, y) {return x + y;}
7.2函数的重复声明
如果同一个函数被多次声明,后面的声明就会覆盖前面的声明
function f() {console.log(1);}f() // 2function f() {console.log(2);}f() // 2
7.3圆括号运算符,return 语句和递归
function add(x, y) {return x + y;}add(1, 1) // 2
上面代码中,函数名后面紧跟一对圆括号,就会调用这个函数。
函数体内部的return语句,表示返回。JavaScript引擎遇到return语句,就直接返回return后面的那个表达式的值,后面即使还有语句,也不会得到执行。也就是说,return语句所带的那个表达式,就是函数的返回值。return语句不是必需的,如果没有的话,该函数就不返回任何值,或者说返回undefined。
函数可以调用自身,这就是递归(recursion)。下面就是通过递归,计算斐波那契数列的代码
function fib(num) {if (num === 0) return 0;if (num === 1) return 1;return fib(num - 2) + fib(num - 1);}fib(6) // 8
7.4第一等公民
JavaScript 语言将函数看作一种值,与其它值(数值、字符串、布尔值等等)地位相同。凡是可以使用值的地方,就能使用函数。比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处
function add(x, y) {return x + y;}// 将函数赋值给一个变量var operator = add;// 将函数作为参数和返回值function a(op){return op;}a(add)(1, 1)// 2
7.5函数作用域
作用域(scope)指的是变量存在的范围。在 ES5 的规范中,JavaScript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。ES6 又新增了块级作用域,本教程不涉及
对于顶层函数来说,函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取
/* 全局作用域 */var a = 1;function f() {/* 函数作用域 */var b=2;console.log(a);}f() // 1console.log(b) // ReferenceError: b is not defined
函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关
var a = 1;var x = function () {console.log(a);};function f() {var a = 2;x();}f()
