美文网首页我爱编程
JavaScript 数据类型浅析

JavaScript 数据类型浅析

作者: JK_TanTan | 来源:发表于2018-05-17 10:32 被阅读0次

    概述

    JavaScript有六种简单的数据类型和一种较复杂的数据类型。简单数据类型有:Undefined、Null、Boolean、Number、String、Symbol (ECMAScript 6 新定义),复杂类型Object,可进一步细分为Array、function、Date等。

    Undefined

    Undefined只有一个值,使用var声明变量但不给这个变量赋值,或者既没有声明也没有初始化,那么这个变量的类型就是Undefined,前者默认初始值是Undefined,后者没有默认初始值。

    Null

    Null是第二个只有一个值的类型,null值表示的是一个空对象指针,因此在使用typeof检测时会返回object。

    Boolean

    Boolean有两个字面值true、false,但这两个值不一定就等于1、0,JavaScript里面所有类型的值都有与Boolean值等价的值,调用Boolean()即可转化一个值为Boolean类型。转化规则如下:

    transform

    Number

    Number用来表示整数和浮点数值,还有一种特殊数值:NaN(not a number非数值),js中任何数值除以0会返回NaN(但测试显示只有0/0为NaN,其它为Infinity无穷大),不会像其他语言那样报错停止代码执行。

    NaN有两个重要的特点:任何涉及到NaN的操作都会返回NaN(eg:NaN/2返回NaN),NaN与任何值都不相等,包括与其本身,NaN==NaN 返回false。isNaN()可以判断值是否“不是数值”,他会尝试将测试值转变为数值:

    isNaN(NaN);    //true    
    isNaN(10);    //false(10是一个数值)    
    isNaN("10");    //false(可能被转换为数值10)    
    isNaN("blue");    //true(不能被转换为数值)    
    isNaN(true);    //false(可能被转换为数值1)     
    

    数值转换:Number()可用于任何类型转换为number;parseInt()、parseFloat()用于字符串转换为number;不能转换返回NaN。

    parseInt()函数在转换字符串时,它会忽略字符串前面的空格,直至找到第一个非空格字符。如果第一个字符串不是数字字符或者负号,parseInt()会返回NaN;如果第一个字符是数字字符,praseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。例如,"1234blue"会被转换为1234,”22.5“会被转换为22,因为小数点并不是有效的数字字符。 parseInt()也能够识别出各种整数格式(即十进制、八进制、十六进制)。可设置两个参数

     parseInt("解析值",2);//按二进制解析    
    

    parseFloat()也是从第一个字符(位置0)开始解析每个字符,一直解析到字符串末尾或者解析到遇见一个无效的浮点数字字符为止。也就是说,字符串中的第一个小数点是有效的,而第二个小数点就是无效的了,它后面的字符串将被忽略。例如,”22.34.5“将会被转换成22.34。parseFloat()和parseInt()的另一个区别在于它始终都会忽略前导的零,且只解析十进制值,没有第二个参数。

    parseInt("3.345");  //  3
    parseInt("AF");       //56(八进制)
    parseFloat("3.345");    //3.345   
    parseFloat("0xA");        //0
    

    String

    String表示字符串,0个或多个字符组成,用''或""表示。可使用.length获取字符串长度。
    将一个值转换成String类型有两个方法,toString()和String(),前者对Undefined、null类型不适用,后者均可用。

    toString()一般不传参数,默认10,表示十进制,若果传递toString(2),表示二进制,以此类推。

    Symbols符号类型

    符号(Symbols)是ECMAScript 第6版新定义的。符号类型是唯一的并且是不可修改的, 并且也可以用来作为Object的key的值。 在某些语言当中也有类似的原子类型(Atoms),可以认为为它们是C里面的枚举类型。

    Object

    Object是一组数据和功能的集合。在计算机科学中,对象是指内存中的可以被标识符引用的一块区域。实例化对象的过程有两种,一是通过new操作符,二是通过对象字面量表示法。

    第一种:使用new操作符后跟Object()构造函数,示例:

    var person = new Object();
    person.name = "Nicholas";
    person.age = 29;
    

    第二种:使用对象字面量表示法。对象字面量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程,属性名也可以使用字符串"name":"nick"。这种语法要求的代码量少,而且能够给人封装数据的感觉,更推崇。例:

    var person = {
        name : "Nicholas",
        age : 29
    }
    

    obj只是引用类型,是堆内存中一个对象的别称,本身并不占用内存。实例化对象地址存到栈内存中,然后通过地址访问堆内存。js中,函数的参数都是值传递的,而对于js内的引用类型,其值默认为栈内存中的地址。

    Object的每个实例常见属性和方法:

    • constructor——保存着用于创建当前对象的函数
    • hasOwnProperty(propertyName)——用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在。其中,作为参数的属性名(propertyName)必须以字符串形式指定(例如:o.hasOwnProperty("name"))
    • isPrototypeOf(object)——用于检查传入的对象是否是另一个对象的原型
    • propertyIsEnumerable(propertyName)——用于检查给定的属性是否能够使用for-in语句来枚举
    • toString()——返回对象的字符串表示
    • valueOf()——返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同。

    数据类型的判断

    typeof

    typeof是平常用的检测变量类型方法,但是arr, json, null, date, reg, error类型均会被检测为object类型,其他类型能够精确的检测。使用方法:typeof 变量名;输出类型。

    var num = 3;       
    typeof num; //number
    

    instance

    instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。使用方法:变量名 instanceof 特定类型名。返回true、false。能检测出多层继承的关系。

    function Person(){
    
    }
    function Student(){
    
    }
    Student.prototype = new Person();
    var John = new Student();
    console.log(John instanceof Student); // true
    console.log(John instancdof Person);  // true   
    

    普通声明num, str和bool不能检测出他的类型,只有以var num = new Number(123);这种方式声明的才可以检测出。此外,undefined和null是检测不成Object类型的,所以检测前需要先判断是否是undefined和null。

    constructor

    使用instanceof检测变量类型时,检测不到number, string, bool的类型。constructor本来是原型对象上的属性,指向构造函数。但是根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的。除了undefined和null,其他类型的变量均能使用constructor判断出类型。 使用方法:变量名.constructor==特定类型名。返回true、false。

    // undefined和null没有constructor属性
    console.log(
        Tom.constructor==Person,
        num.constructor==Number,
        str.constructor==String,
        bool.constructor==Boolean,
        arr.constructor==Array,
        json.constructor==Object,
        func.constructor==Function,
        date.constructor==Date,
        reg.constructor==RegExp,
        error.constructor==Error
    );
    // 所有结果均为true
    

    但constructor属性是可以被修改的,会导致检测出的结果不正确。

    function Person(){
    
    }
    function Student(){
    
    }
    Student.prototype = new Person();
    var John = new Student();
    console.log(John.constructor==Student); // false
    console.log(John.constructor==Person);  // true
    

    Object.prototype.toString.call

    Object.prototype.toString.call(变量)输出的是一个字符串,

    console.log(
        Object.prototype.toString.call(num),// '[object Number]'
        Object.prototype.toString.call(str),// '[object String]'
        Object.prototype.toString.call(bool),// '[object Boolean]'
        Object.prototype.toString.call(arr),// '[object Array]'
        Object.prototype.toString.call(json),// '[object Object]'
        Object.prototype.toString.call(func),// '[object Function]'
        Object.prototype.toString.call(und),// '[object Undefined]'
        Object.prototype.toString.call(nul),// '[object Null]'
        Object.prototype.toString.call(date),// '[object Date]'
        Object.prototype.toString.call(reg),// '[object RegExp]'
        Object.prototype.toString.call(error)// '[object Error]'
    );
    

    字符串里有一个数组,第一个参数是Object,第二个参数就是这个变量的类型,而且,所有变量的类型都检测出来了,我们只需要取出第二个参数即可。或者可以使用Object.prototype.toString.call(arr)=="object Array"来检测变量arr是不是数组。

    他是怎么检测变量类型的:

    1. 首先,取得对象的一个内部属性[[Class]],
    2. 然后依据这个属性,返回一个类似于”[object Array]”的字符串作为结果([[]]用来表示语言内部用到的、外部不可直接访问的属性,称为“内部属性”)。
    3. 利用这个方法,再配合call,我们可以取得任何对象的内部属性[[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。

    jquery中$.type

    使用方法:$.type(变量名)。返回类型名,如:number string boolean。

    $.type方法的实现,实质上就是综合typeof和Object.prototype.toString.call两种方式:

    // 实例对象是能直接使用原型链上的方法的
    var class2type = {};
    var toString = class2type.toString;
    
    // 省略部分代码...
    
    type: function( obj ) {
        if ( obj == null ) {
        // 若传入的是null或undefined,则直接返回这个对象的字符串
        // 即若传入的对象obj是undefined,则返回"undefined"
            return obj + "";
        }
        
        // 若使用typeof检测出的obj类型是object或function,则返回class2type的值,否则返回typeof检测的类型
        return (typeof obj === "object" || typeof obj === "function") ?
            (class2type[ toString.call(obj) ] || "object") :
            typeof obj;
    },
    
    // 省略部分代码... 
    
    // Populate the class2type map
    jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
        class2type[ "[object " + name + "]" ] = name.toLowerCase();
    });
    

    区分 Undefined 和 Null

    相似点

    将一个变量赋值为undefined或null,几乎没区别。undefined和null在if语句中,都会被自动转为false,相等运算符甚至直接报告两者相等。他们都是完全不可变的,没有属性和方法,也不能给其属性赋值。使用相等操作符( == )比较这两个值和其他false值,他们并不等于除了自己:

    null == 0; // false
    undefined == ""; // false
    null == false; // false
    undefined == false; // false
    null == undefined; // true
    undefined === null; // false,类型不同
    

    差异

    null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时都为NaN。换句话说,null表示"没有对象",即该处不应该有值。undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。

    null

    通常用作一个空引用一个空对象的预期,就像一个占位符。

    • DOM,它是独立于语言的,不属于ECMAScript规范的范围。因为它是一个外部API,试图获取一个不存在的元素返回一个null值,而不是undefined。
    • 如果你需要给一个变量或属性指定一个不变值,将它传递给一个函数,或者从一个函数返回null,null几乎是最好的选择。
    • object= null,通过分配null值,有效地清除引用,并假设对象没有引用其他代码,指定垃圾收集,确保回收内存。

    undefined

    var i;
    i // undefined
    
    function f(x){console.log(x)}
    f() // undefined
    
    var  o = new Object();
    o.p // undefined
    
    var x = f();
    x // undefined
    
    • 变量被声明了,但没有赋值时,就等于undefined。
    • 调用函数时,应该提供的参数没有提供,该参数等于undefined。
    • 对象没有赋值的属性,该属性的值为undefined。
    • 函数没有返回值时,默认返回undefined。

    相关文章

      网友评论

        本文标题:JavaScript 数据类型浅析

        本文链接:https://www.haomeiwen.com/subject/monvdftx.html