Javascript数据类型之基本数据类型

 本文并不是对javascript的各个基本数据类型做详细的介绍,而是对javascript基本数据类型的疑难问题(特别是与其他语言不太一样的地方)做详细说明。

概述

  javascript包含六个基本的数据类型:String, Number, Boolean, Undefined, Null, Object。对于Null,Function是不是基本的数据类型,一直有争议,存在不同的说法。有些人认为Null不是一个数据类型,因为typeof null === 'object'。有些人认为Function应该是一个基本的数据类型,因为 typeof function(){} === "function". 按照ecmascript规范的定义,Null是一个数据类型,而function是属于Object类型。 typeof的结果和javascript的基本数据类型不是一一对应的,这是浏览器实现的历史遗留问题(为了向后兼容)。
  String, Number, Boolean, Undefined, Null是原始(primitive)类型(最近的es6中新增加了Symbol原始类型)。原始类型是值类型,而Object类型是引用类型
  下面将对基本数据类型中的一些疑难问题做详细说明。

1. String

  javascript的字符串既可以用单引号来标识,也可以用双引号。在字符串有引号的时候,我们可以使用不同的引号来标识字符串,或将字符串中的引号转义。本节示例如下:

    // 使用与字符串中不同的引号来标识字符串
    'This is "Africa".'
    "This is 'Africa'."
    // 将字符串中的引号转义
    "This is \"Africa\"."
    'This is \'Africa\'.'

  在javascript中没有char类型,我们可以用包含单个字符的字符串来替代char类型。我们可以使用String.prototype.charCodeAt方法将char转换成ASCII码,可以使用String.fromCharCode方法将ASCII码转换成char。本节示例如下:

    "e".charCodeAt(0);    // 101
    String.fromCharCode(101);    // "e"

  javascript的字符串中可以使用Unicode字符(\u加4位16进制数字)。本节示例如下:

    "兰芳\u5171\u548c\u56fd" // "兰芳共和国"

2. Number

  javascript中的数字可以用科学计数法表示,一般在数字太大或太小时使用。本节示例如下:

    1.2e5;    // 120000
    1.2e-5;    // 0.000012

  javascript数字除了能用十进制表示外,还可以用8进制和16进制表示。数字的16进制表示,以"0x"起始,加上16进制数字(0-9A-F)。数字的8进制表示以"0"起始,加上8进制数字(0-8)。16进制数字和8进制数字都不能有小数,也不能用科学计数法表示。本节示例如下:

    var a = 0xa3b;    // 2619
    var b = 072;    // 58
    b/2;            // 29

    0xa.3b;    // SyntaxError: Unexpected token ILLEGAL
    01e3;    // SyntaxError: Unexpected token ILLEGAL

  javascript数字类型有一个特殊的值NaN。NaN字面的意思就是"不是一个数字"(Not a Number)。在javascript中对非法的数据进行数字操作的时候就会返回NaN,当然对NaN进行数学运算也返回NaN。NaN的特殊之处还在与NaN不等于NaN,判断NaN可以使用全局函数isNaN.本节示例如下:

    // 非法的数据进行数字操作
    parseInt("a01");    // NaN
    Math.sqrt(-1);        // NaN
    "b" * 1;            // NaN

    // 对NaN进行数学运算的结果为NaN
    NaN + 1;            // NaN
    NaN * 12;            // NaN

    // NaN不等于NaN
    NaN == NaN;            // false

    // 判断是否为 NaN
    isNaN(NaN);            // true

  javascript数字类型还有一个特殊的值Infinity,用来表示无穷大(比任何其他的数字都要大)。javascript里的数字都在-infinity和infinity之间。本节示例如下:

    1/0;                // Infinity
    9999/Infinity;        // 0
    Infinity/Infinity;    // NaN

3. Boolean

  javascript布尔类型比较简单,只有两个取值(true/false)。   javascript中"&&","||"操作的运算结果并不一定是布尔型,也就是说运算结果并不会强制转换成布尔型。利用这个特性,我们常用"&&"来做条件赋值,用"||"来做默认值设置。本节示例如下:

    // "&&", "||"计算结果不会转换成布尔型
    1&&0;    // 0
    "tom" || "jerry";    // "tom"

    // 使用"&&"条件赋值
    var tom = {name: "tom", age: 10};
    var age = tom && tom.age;

    // 使用"||"设置默认值
    var option = option || {country: 'China'};

4. Undefined

  Undefined类型只有一个值undefined,表示没有值。除显式的赋值为undefined外,下面情况下会产生undefined:

  1. 变量声明但没有赋值
  2. 获取对象不存在的属性
  3. 函数没有返回
  4. 函数的参数没有传入
  5. void(expression)

本节示例如下:

    // 变量声明但没有赋值
    var a;
    a;        // undefined

    // 获取对象不存在的属性
    var tom = {name: "tom", age: 10};
    tom.gender;        // undefined

    // 函数没有返回值
    function fn(){}
    fn();   // undefined

    function foo(){
        return;
    }
    foo();  //undefined

    // 函数的参数没有传入
    function sum(x, y){
        return y;
    }
    sum(1); // undefined

    // void(expression)
    void(0);    //undefined

5. Null

  Null类型也只有一个值null。变量或属性赋值为null来表示空值。上文也已经提过,typeof null等于"object",而不等于"null",这个让人困惑的行为主要是为了向后兼容。本节示例如下:

    var a = null;
    typeof a;    // "object"

6. Object

  对象是一组属性的集合。Javascript可以通过对象字面量创建对象,也可以使用构造函数创建对象。本节示例如下:

    // 对象字面量创建对象
    var obj = {name: 'jerry', age: 0};

    // 通过构造函数创建对象
    var obj = new Object({name: 'jerry', age: 0});
    // 通过构造函数创建对象的另一种方式
    var obj = Object({name: 'jerry', age: 0});

  String/Number/Boolean/Array/Date继承自Object, 也就是说String/Number/Boolean/Array/Date对象都是一种Object对象, 它们可以使用Object中的属性和方法。这里可能有些让人迷惑,我们前面说了String类型/Number类型/Boolean类型,这里为什么又说String对象/Number对象/Boolean对象其实是一种Object对象。让我们先来看一个示例:

    // 用字面量创建的,是原始类型
    typeof "jerry"; // "string"
    typeof 1;    // "number"
    typeof false;    // "boolean"

    // 用构造函数创建的,是Object类型
    typeof new String("jerry");    // "object"
    typeof Number(1);    // "object"
    typeof new Boolean(false);    // "object"

    // String/Number/Boolean等对象,可以使用Object中的属性和方法(hasOwnProperty/valueOf/toString都是Object的方法)
    var a = new String("jerry");
    a.hasOwnProperty("length");        // true
    Number(1).valueOf();    // 1
    new Boolean(false).toString();    // "false"

 我们再来看个例子:

    // 原始类型调用Obejct的方法
    "jerry".hasOwnProperty("length");    // true
    1.valueOf();    // SyntaxError: Unexpected token ILLEGAL
    (1).valueOf();  // 1
    false.toString();    // "false"

  我们发现字面量创建的原始类型也能调用Object中的方法,这又是为什么呢?因为javascript引擎发现用原始类型调用Object的方法时,会把原始类型包装成Object类型, "jerry".hasOwnProperty("length")等同于new String("jerry").hasOwnProperty("length")。那为什么1.valueOf()会语法错误呢?因为浏览器读到1.时会认为要创建个小数,但是1.valueOf()不是一个合法的小数。我们可以通过加括号的方式解决这个问题。

结语

  因为ecmascript里面并没有"基本类型"这个说法,对于javascript的基本类型的说法有争议,本文并不是想参与这些争论,而是介绍javascript类型中的疑难问题(特别是与其他语言不太一样的地方)。
  进一步了解Javascript类型系统:

本文来自网易实践者社区,经作者魏文庆授权发布。