美文网首页
数据类型

数据类型

作者: hhooke | 来源:发表于2018-08-25 09:33 被阅读0次

    ps : 本人学习笔记

    类型

    • 空值( null )
    • 未定义( undefined )
    • 布尔值( boolean )
    • 数字( number )
    • 字符串( string )
    • 对象( object )
    • 符号( symbol , ES6 中新增

    注意null

    typeof null === "object"; // true
    

    检测null类型

    var a = null;
    
    (!a && typeof a === "object"); // true
    

    function

    很多人搞不清函数和Object的关系,查阅规范可以知道,它实际上是 object 的一个 “ 子类型 ” 。具体来说,函数是 “ 可调用对象 ” ,它有一个内部属性 [[Call]] ,该属性使其可以被调用。函数不仅是对象,还可以拥有属性。

    function fn(a,b){}
    
    console.log(fn.length)// 2
    

    函数对象的 length 属性是其声明的参数的个数

    数组也属于object的一个子类型

    数组

    数组通过数字进行索引,但有趣的是它们也是对象,所以也可以包含字符串键值和属性(但这些并不计算在数组长度内)

    var a = []
    
    a[0] = 1;
    a['asda'] = 'asd'
    
    console.log(a.length) //1
    

    如果字符串键值能够被强制类型转换为十进制数字的话,它就会被当作数字索引来处理

    var a = [ ];
    a["13"] = 42;
    a.length; // 14
    

    类数组

    一些DOM操作返回的集合 就是类数组

    通过arguments 对象(类数组)将函数的参数当作列表来访问(从 ES6 开始已废止)。

    function foo() {
        var arr = Array.prototype.slice.call(arguments);
        arr.push("bam");
        console.log(arr);
    }
    foo("bar", "baz"); // ["bar","baz","bam"]
    

    ES6 中的内置工具函数 Array.from(..) 也能实现同样的功能

    var arr = Array.from( arguments );
    

    字符串

    字符串和数组的确很相似,它们都是类数组,都有 length 属性以及 indexOf(..) (从 ES5 开始数组支持此方法)和concat(..) 方法:

    var a = "foo";
    var b = ["f","o","o"];
    
    a.length; // 3
    b.length; // 3
    
    a.indexOf( "o" ); // 1
    b.indexOf( "o" ); // 1
    
    var c = a.concat( "bar" ); // "foobar"
    var d = b.concat( ["b","a","r"] ); // ["f","o","o","b","a","r"]
    
    a === c; // false
    b === d; // false
    
    a; // "foo"
    b; // ["f","o","o"]
    
    a[1] = "O";
    b[1] = "O";
    
    a; // "foo"
    b; // ["f","O","o"]
    

    JavaScript 中字符串是不可变的,而数组是可变的。并且 a[1] 在 JavaScript 中并非总是合法语法,在老版本的 IE 中就不被允许(现在可以了)。 正确 的方法应该是 a.charAt(1) 。

    var a = 'foo'
    a[0] = 'h'
    console.log(a[0]) // f
    

    许多数组函数用来处理字符串很方便。虽然字符串没有这些函数,但可以通过 “ 借用 ” 数组的非变更方法来处理字符串

    数字

    特别大和特别小的数字默认用指数格式显示,与 toExponential() 函数的输出结果相同

    var a = 5E10;
    a; // 50000000000
    a.toExponential(); // "5e+10"
    var b = a * a;
    b; // 2.5e+21
    var c = 1 / a;
    c; // 2e-11
    

    由于数字值可以使用 Number 对象进行封装(参见第 3 章),因此数字值可以调用 Number.prototype 中的方法。例如, tofixed(..) 方法可指定小数部分的显示位数

    var a = 42.59;
    a.toFixed( 0 ); // "43"
    a.toFixed( 1 ); // "42.6"
    a.toFixed( 2 ); // "42.59"
    a.toFixed( 3 ); // "42.590"
    a.toFixed( 4 ); // "42.5900"
    

    toPrecision(..) 方法用来指定 有效数位 的显示位数

    var a = 42.59;
    a.toPrecision( 1 ); // "4e+1"
    a.toPrecision( 2 ); // "43"
    a.toPrecision( 3 ); // "42.6"
    a.toPrecision( 4 ); // "42.59"
    a.toPrecision( 5 ); // "42.590"
    a.toPrecision( 6 ); // "42.5900"
    

    数字常量还可以用其他格式来表示,如二进制、八进制和十六进制。
    当前的 JavaScript 版本都支持这些格式:

    0xf3; // 243 的十六进制
    0Xf3; //  同上
    0363; // 243 的八进制
    

    计算问题

    二进制浮点数中的 0.1 和 0.2 并不是十分精确,它们相加的结果并非刚好等于 0.3 ,而是一个比较接近的数字0.30000000000000004

    整数检测

    要检测一个值是否是整数,可以使用 ES6 中的 Number.isInteger(..) 方法

    要检测一个值是否是 安全的整数 ,可以使用 ES6 中的 Number.isSafeInteger(..) 方法

    void 运算符

    undefined 是一个内置标识符(除非被重新定义,见前面的介绍),它的值为 undefined ,通过 void 运算符即可得到该值。

    var a = 42;
    console.log( void a, a ); // undefined 42
    

    特殊的数字

    不是数字的数字 NAN

    NAN : 不是数字 将它理解为 “ 无效数值 ”“ 失败数值 ” 或者 “ 坏数值 ” 可能更准确些

    var a = 2 / "foo";
    isNaN( a ); // true
    

    很明显 "foo" 不是一个数字 ,但是它也不是 NaN 。这个 bug 自 JavaScript 问世以来就一直存在,至今已超过 19 年

    从 ES6 开始我们可以使用工具函数 Number.isNaN(..)

    无穷数

    var a = 1 / 0; // Infinity
    var b = -1 / 0; // -Infinity
    

    特殊等式

    如前所述, NaN 和 -0 在相等比较时的表现有些特别。由于 NaN 和自身不相等,所以必须使用 ES6 中的Number.isNaN(..) (或者 polyfill )。而 -0 等于 0 (对于 === 也是如此),因此我们必须使用isNegZero(..) 这样的工具函数。

    ES6 中新加入了一个工具方法 Object.is(..) 来判断两个值是否绝对相等,可以用来处理上述所有的特殊情况

    var a = 2 / "foo";
    var b = -3 * 0;
    Object.is( a, NaN ); // true  NaN 只和自身不相等
    Object.is( b, -0 ); // true
    Object.is( b, 0 ); // false
    

    基本类型和引用类型

    基本类型 : 总是 通过值复制的方式来赋值 / 传递,包括 null 、 undefined 、字符串、数字、布尔和 ES6 中的 symbol 。

    引用类型 : 当复制保存着对象的某个变量时,操作的是对象的引用,但在为对象添加属性时,操作的是实际的对象。

    在复制变量值时,基本类型会在变量对象上创建一个新值,再复制给新变量。此后,两个变量的任何操作都不会影响到对方;而引用类型是将存储在变量对象的值复制一份给新变量,但是两个变量的值都指向存储在堆中的一个对象,也就是说,其实他们引用了同一个对象,改变其中一个变量就会影响到另一个变量。

    //基本类型值
    var a = 'a';
    var b = a;
    a = 'b';
    console.log(b); //a
    
    //引用类型值,以数组为例
    
    //1.对其中一个变量直接赋值不会影响到另一个变量(并未操作引用的对象)
    var a = [1,2,2,6,4]
    var b = a;
    a = [4,5,6,7]
    console.log(b) //[ 1, 2, 2, 6, 4 ]
    
    //2.使用push(操作了引用的对象)
    var a = [1,2,3];
    var b = a;
    a.push(4);
    console.log(a);//1,2,3,4
    console.log(b); //1,2,3,4
    

    对象参数传递

    var a = [1,2,3,4]
    
    function pusha(arr) {
        arr.push(5)
    }
    
    pusha(a)
    
    console.log(a)
    

    a的值会被传递到pusha里,此时传的是a的地址,pusha执行的时候其实是在操作a。

    内部属性 [[class]]

    所有 typeof 返回值为 "object" 的对象(如数组)都包含一个内部属性 [[Class]]

    一般通过 Object.prototype.toString(..) 来查看

    Object.prototype.toString.call( [1,2,3] ); // "[object Array]"
    
    Object.prototype.toString.call( /regex-literal/i ); // "[object RegExp]"
    

    封装对象包装

    封装对象( object wrapper )扮演着十分重要的角色。由于基本类型值没有 .length 和 .toString() 这样的属性和方法,需要通过封装对象才能访问,此时 JavaScript 会自动为基本类型值 包装一个封装对象

    var a = "abc";
    a.length; // 3
    a.toUpperCase(); // "ABC"
    Object.prototype.toString.call( a ); // "[object String]"
    

    js引擎会自动帮我们封装,在我们使用这些属性的时候,所以我们不必提前的将他们对象化,否则会降低执行效率。

    封装对象释疑

    使用封装对象时有些地方需要特别注意。比如 Boolean :

    var a = new Boolean(false);
    if (!a) {
        console.log("Oops"); //  执行不到这里
    }
    

    我们为 false 创建了一个封装对象,然而该对象是真值( “truthy” ,即总是返回 true),所以这里使用封装对象得到的结果和使用 false 截然相反。如果想要自行封装基本类型值,可以使用 Object(..) 函数(不带 new 关键字):

    var a = "abc";
    var b = new String( a );
    var c = Object( a );
    
    typeof a; // "string"
    typeof b; // "object"
    typeof c; // "object"
    
    b instanceof String; // true
    c instanceof String; // true
    
    Object.prototype.toString.call( b ); // "[object String]"
    Object.prototype.toString.call( c ); // "[object String]"
    

    拆封

    如果想要得到封装对象中的基本类型值,可以使用 valueOf() 函数

    var a = new String( "abc" );
    var b = new Number( 42 );
    var c = new Boolean( true );
    
    a.valueOf(); // "abc"
    b.valueOf(); // 42
    c.valueOf(); // true
    

    相关文章

      网友评论

          本文标题:数据类型

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