1.简介

JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有八种,但我们先只学习其中常见的的六种

  • 数值number:整数和小数(比如13.14
  • 字符串string:文本(比如"Hello World"'Hello World'
  • 布尔值boolean:表示真伪的两个特殊值,即true(真)和false(假)
  • undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值(该类型的值唯一并且为其本身)
  • null:表示空值,即此处的值为空(该类型的值唯一并且为其本身)
  • 对象object:各种键值对组成的集合(此处指广义的对象)
    • 狭义的对象object
    • 数组array
    • 函数function
    • 等等……

      2.typeof运算符

      ```javascript typeof 123 // “number” typeof ‘123’ // “string” typeof false // “boolean”

// 函数返回”function” function f() {} typeof f // “function”

// undefined返回”undefined” typeof undefined // “undefined”

// 对象返回”object”({}为狭义对象的声明方式之一,[]为数组的声明方式之一) typeof {} // “object” typeof [] // “object”

  1. ```javascript
  2. typeof null // "object"

null的类型是object,这是由于历史原因造成的。1995年的 JavaScript 语言第一版,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),没考虑null,只把它当作object的一种特殊值。后来null独立出来,作为一种单独的数据类型,为了兼容以前的代码,typeof null返回object就没法改变了


3.数值

3.1数值的表示方法

  1. // 可以使用科学表示法
  2. 123000 === 123e3 // true
  3. 0.123 === 123e-3 // true
  4. // 表示小数时可省略0
  5. 0.123 === .123 // true

3.2数值的进制

使用字面量(literal)直接表示一个数值时,JavaScript 对整数提供四种进制的表示方法:十进制、十六进制、八进制、二进制。

  • 十进制:没有前导0的数值。
  • 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。
  • 十六进制:有前缀0x或0X的数值。
  • 二进制:有前缀0b或0B的数值。

默认情况下,JavaScript 内部会自动将八进制、十六进制、二进制转为十进制。下面是一些例子。

  1. 0xff // 255
  2. 0o377 // 255
  3. 0b11 // 3

如果八进制、十六进制、二进制的数值里面,出现不属于该进制的数字,就会报错

  1. 0xzz // 报错
  2. 0o88 // 报错
  3. 0b22 // 报错

3.3NaN

NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合

  1. 5 - 'x' // NaN

需要注意的是,NaN不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number,使用typeof运算符可以看得很清楚

  1. typeof NaN // 'number'

4.字符串

4.1字符串书写方式

字符串就是零个或多个排在一起的字符,放在单引号或双引号之中

  1. 'abc'
  2. "abc"

单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号

  1. 'key = "value"'
  2. "It's a long journey"

字符串默认只能写在一行内,分成多行将会报错

  1. 'a
  2. b
  3. c'
  4. // SyntaxError: Unexpected token ILLEGAL

如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠或连接运算符+

  1. 'Long \
  2. long \
  3. long \
  4. string'
  5. 'Long '
  6. + 'long '
  7. + 'long '
  8. + 'string'

4.2字符串遍历方式

  1. var str='我是一个字符串';
  2. // 读取方式(字符串与数组类似,可通过索引读取)
  3. str[0] // '我'
  4. str.length // 7
  5. // 遍历方式
  6. for(var i=0; i<str.length; i++){
  7. console.log(str[i]);
  8. }

5.对象

5.1对象生成方法

对象(object)是 JavaScript 语言的核心概念,也是最重要的数据类型
什么是对象?简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合

  1. var obj = {
  2. foo: 'Hello',
  3. bar: 'World'
  4. };

上面代码中,大括号就定义了一个对象,它被赋值给变量obj,所以变量obj就指向一个对象。该对象内部包含两个键值对(又称为两个“成员”),第一个键值对是foo: 'Hello',其中foo是“键名”(成员的名称),字符串Hello是“键值”(成员的值)。键名与键值之间用冒号分隔。第二个键值对是bar: 'World'bar是键名,World是键值。两个键值对之间用逗号分隔

5.2对象属性的增删改查(新增、删除、修改、查询)

  1. var obj = {
  2. foo: 'Hello',
  3. bar: 'World'
  4. };
  5. // 两种查询方式
  6. obj.foo // 'Hello'
  7. obj['bar'] // 'World'
  8. // 通过赋值语句进行新增和修改
  9. obj.a='你好';
  10. obj.bar='世界';
  11. obj.bar // '世界'
  12. // delete删除命令
  13. delete obj.bar
  14. obj.bar // undefined

5.3对象的引用

  1. var o1 = {};
  2. var o2 = o1;
  3. o1.a = 1;
  4. o2.a // 1
  5. o2.b = 2;
  6. o1.b // 2

上面代码中,o1o2指向同一个对象,因此为其中任何一个变量添加属性,另一个变量都可以读写该属性。
此时,如果取消某一个变量对于原对象的引用,不会影响到另一个变量

  1. var o1 = {};
  2. var o2 = o1;
  3. o1 = 1;
  4. o2 // {}

但是,这种引用只局限于对象,如果两个变量指向同一个原始类型的值。那么,变量这时都是值的拷贝

  1. var x = 1;
  2. var y = x;
  3. x = 2;
  4. y // 1

上面的代码中,当x的值发生变化后,y的值并不变,这就表示yx并不是指向同一个内存地址

5.4对象属性的遍历

  1. var obj = {
  2. foo: 'Hello',
  3. bar: 'World'
  4. };
  5. // 方式一:通过Object.keys(obj)获取所有键名数组,然后遍历数组来访问对象属性
  6. var keys = Object.keys(obj)
  7. keys // ['foo','bar']
  8. for(var i=0; i<keys.length; i++){
  9. console.log(obj[ keys[i] ]);
  10. }
  11. // 方式二:for...in循环
  12. for(var key in obj){
  13. console.log('键名',key);
  14. console.log('键值',obj[key]);
  15. }

6.数组

6.1数组生成方法

数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示

  1. var arr=['a','b','c'];

上面代码中的'a''b''c'就构成一个数组,两端的方括号是数组的标志。'a'0号位置,'b'1号位置,'c'2号位置
除了在定义时赋值,数组也可以先定义后赋值

  1. var arr=[];
  2. arr[0] = 'a';
  3. arr[1] = 'b';
  4. arr[2] = 'c';

任何类型的数据,都可以放入数组

6.2数组的本质

  1. typeof [1, 2, 3] // "object"

上面代码表明,typeof运算符认为数组的类型就是对象。
数组的特殊性体现在,它的键名是按次序排列的一组整数(0,1,2…)。

  1. var arr = ['a', 'b', 'c'];
  2. Object.keys(arr)
  3. // ["0", "1", "2"]

6.3length属性

数组的length属性,返回数组的成员数量

  1. ['a', 'b', 'c'].length // 3

6.4数组的遍历方式

  1. var arr=[1,2,3];
  2. // 方式一:通过length确定长度,使用循环依次读取
  3. for(var i=0; i<arr.length; i++){
  4. console.log(arr[i]);
  5. }
  6. // 方式二:for...in循环
  7. for(var i in arr){
  8. console.log(arr[i]);
  9. }

7.函数

7.1函数的声明

  1. function命令

function命令声明的代码区块,就是一个函数。function命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函数体放在大括号里面

  1. function print(s) {
  2. console.log(s);
  3. }
  1. 函数表达式

除了用function命令声明函数,还可以采用变量赋值的写法

  1. var print = function(s) {
  2. console.log(s);
  3. };
  1. Function构造函数

第三种声明函数的方式是Function构造函数

  1. var add = new Function(
  2. 'x',
  3. 'y',
  4. 'return x + y'
  5. );
  6. // 等同于
  7. function add(x, y) {
  8. return x + y;
  9. }

7.2函数的重复声明

如果同一个函数被多次声明,后面的声明就会覆盖前面的声明

  1. function f() {
  2. console.log(1);
  3. }
  4. f() // 2
  5. function f() {
  6. console.log(2);
  7. }
  8. f() // 2

7.3圆括号运算符,return 语句和递归

  1. function add(x, y) {
  2. return x + y;
  3. }
  4. add(1, 1) // 2

上面代码中,函数名后面紧跟一对圆括号,就会调用这个函数。
函数体内部的return语句,表示返回。JavaScript引擎遇到return语句,就直接返回return后面的那个表达式的值,后面即使还有语句,也不会得到执行。也就是说,return语句所带的那个表达式,就是函数的返回值。return语句不是必需的,如果没有的话,该函数就不返回任何值,或者说返回undefined
函数可以调用自身,这就是递归(recursion)。下面就是通过递归,计算斐波那契数列的代码

  1. function fib(num) {
  2. if (num === 0) return 0;
  3. if (num === 1) return 1;
  4. return fib(num - 2) + fib(num - 1);
  5. }
  6. fib(6) // 8

7.4第一等公民

JavaScript 语言将函数看作一种值,与其它值(数值、字符串、布尔值等等)地位相同。凡是可以使用值的地方,就能使用函数。比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处

  1. function add(x, y) {
  2. return x + y;
  3. }
  4. // 将函数赋值给一个变量
  5. var operator = add;
  6. // 将函数作为参数和返回值
  7. function a(op){
  8. return op;
  9. }
  10. a(add)(1, 1)
  11. // 2

7.5函数作用域

作用域(scope)指的是变量存在的范围。在 ES5 的规范中,JavaScript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。ES6 又新增了块级作用域,本教程不涉及
对于顶层函数来说,函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取

  1. /* 全局作用域 */
  2. var a = 1;
  3. function f() {
  4. /* 函数作用域 */
  5. var b=2;
  6. console.log(a);
  7. }
  8. f() // 1
  9. console.log(b) // ReferenceError: b is not defined

函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关

  1. var a = 1;
  2. var x = function () {
  3. console.log(a);
  4. };
  5. function f() {
  6. var a = 2;
  7. x();
  8. }
  9. f()