zoukankan      html  css  js  c++  java
  • Javascript中的数据类型知多少

    JavaScript 是一种弱类型或者说动态语言。这意味着你不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。这也意味着你可以使用同一个变量保存不同类型的数据

    根据ECMAScript 5.1的规范,javascript中共有六种数据类型,分别为:UndefinedNullBoolean,NumberStringObject。前五种属于基本类型,最后一种属于Object类型。

    最新的ECMAScript 6 又加了一种类型:Symbol (ECMAScript 6 新定义) 

    基本数据类型

    • Undefined:只有一个值,为undefined,意味着“空值(no value)”,适用于所有数据类型。
    • Null:只有一个值,为null,意味着“空对象(no object)”,只适用于对象类型。(literal)
    • Boolean:有两个值,为truefalse
    • Number:的值是遵循IEEE 754标准的64位浮点数的集合,没有整型数据结构。此外还包含三个特殊的值:NaNInfinity-Infinity
    • String:值是有穷个Unicode字符的集合。必须用'"括起来。

    一、String

    JavaScript的字符串类型用于表示文本数据。它是一组16位的无符号整数值的“元素”。在字符串中的每个元素占据了字符串的位置。第一个元素的索引为0,下一个是索引1,依此类推。字符串的长度是它的元素的数量

    与 C 语言不同,JavaScript 中字符串是不可变的(译注:如,JavaScript 中对字符串的操作一定返回了一个新字符串,原始字符串并没有被改变)

    Javascript中一切都是object-based

    创建string,也有两种类型

    1、使用字面量方式创建的字符串,为基本类型的string //string 实际上保存就是的值,是一个基本类型

    2、使用String()创建的字符串,为基本类型的string  // string

    3、使用构造函数 new String()的方式创建的字符串,为对象类型的 //string 实际上保存的是一个指向字符串对象的指针

    看代码

    var obj = 'abc';
    obj.something = 1;
    var firstChar = obj.charAt(0); //"a"
    console.log(obj.something); //undefined
    //实际上js做了这样的处理
    var obj = 'abc';
    var temp = new String(obj);
    var firstChar = temp.charAt(0); //"a"
    temp.something = 1;
    temp = null;
    console.log(obj.something); //undefined
    

    原因是,创建了一个临时的引用类型变量去访问属性,修改属性,然后就被释放了

    再看一个例子

    var str1 = "javascript"; //typeof str1 == string
    var str2 = String("javascript"); //typeof str2 == string 不推荐
    var str3 = new String('javascript'); //typeof str3 == object
    

    new Sting 和 string的区别

    s1 = "2 + 2";               // creates a string primitive
    s2 = new String("2 + 2");   // creates a String object
    console.log(eval(s1));      // returns the number 4
    console.log(eval(s2));      // returns the string "2 + 2"

    也就是说使用对象的时候,不会做类型转换

    字符串对象的转换 valueof -》 string

    console.log(eval(s2.valueOf())); // returns the number 4
    

    二、boolean

    不要将原始值true false,和值为true false的Boolean对象相混淆

    1、如果Boolean构造函数的参数不是一个布尔值,则该参数会被转换成一个布尔值

    2、如果参数是 0-0null,falseNaNundefined, 或者空字符串 (""),生成的Boolean对象的值为false. 其他任何值,包括任何对象或者字符串"false", 都会创建一个值为true的Boolean对象

    var x = new Boolean(false);
    
    if(x){
    	console.log(x.valueOf(),typeof x); // false  object
    }
    

    上面会执行,很神奇的代码

    不要通过新建Boolean对象的方法来将一个非布尔值转化成布尔值. 直接使用Boolean函数才是正确的

    var x = Boolean(expression);     // 这样用
    var x = new Boolean(expression); // 而不要这样!
    

    初始化的时候

    //false
    var bNoParam = new Boolean();
    var bZero = new Boolean(0);
    var bNull = new Boolean(null);
    var bEmptyString = new Boolean("");
    var bfalse = new Boolean(false);
    
    //true
    var btrue = new Boolean(true);
    var btrueString = new Boolean("true");
    var bfalseString = new Boolean("false");
    var bSuLin = new Boolean("Su Lin");
    

    三、Number

    根据 ECMAScript 标准,JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(253 -1) 到 253 -1)。它并没有为整数给出一种特定的类型。除了能够表示浮点数外,还有一些带符号的值:+Infinity-Infinity 和 NaN (非数值,Not-a-Number)

    数字类型只有一个整数,它有两种表示方法: 0 可表示为 -0 和 +0("0" 是 +0 的简写)。 在实践中,这也几乎没有影响。 例如 +0 === -0 为真。 但是,你可能要注意除以0的时候:

    42 / +0; // Infinity
    42 / -0; // -Infinity

    如果参数无法被转换为数字,则返回 NaN

    在非构造器上下文中 (如:没有 new 操作符),Number 能被用来执行类型转换

    isNAN 类型判断

    Number.isNaN(NaN);        // true
    Number.isNaN(Number.NaN); // true
    Number.isNaN(0 / 0)       // true
    
    // e.g. these would have been true with global isNaN()
    Number.isNaN("NaN");      // false
    Number.isNaN(undefined);  // false
    Number.isNaN({});         // false
    Number.isNaN("blabla");   // false
    
    // These all return false
    Number.isNaN(true);
    Number.isNaN(null);
    Number.isNaN(37);
    Number.isNaN("37");
    Number.isNaN("37.37");
    Number.isNaN("");
    Number.isNaN(" ");

    原型链继承的关系

    console.log(Number.prototype.__proto__ == Object.prototype); //true
    console.log(Number.prototype.__proto__.__proto__ == Object.prototype.__proto__);//true
    console.log(Object.prototype.__proto__ === null);//true
    console.log(typeof Number);//function
    

    使用 Number 转换 Date 对象

    var d = new Date("December 17, 1995 03:24:00");
    console.log(Number(d));
    

    四、Null

    null 是一个 JavaScript 字面量,表示空值(null or an "empty" value),即没有对象被呈现(no object value is present)。它是 JavaScript 原始值 之一。

    null 是一个字面量 (而不是全局对象的一个属性,undefined 是 )

    console.log(null); //null
    console.log(undefined);//undefined
    
    console.log(window.null);//undefined
    console.log(window.undefined);//undefined

    null与undefined的区别

    console.log(foot);//Uncaught ReferenceError: foot is not defined
    
    var foo;
    console.log(foo);//undefined
    
    var bar =null;
    console.log(bar);//null
    
    typeof null        // object (bug in ECMAScript, should be null)
    typeof undefined   // undefined
    null === undefined // false
    null  == undefined // true
    

    所以判断null,可以判断类型 + 值

    五、Undefined

    在JavaScript中,undefined这个词有多重含义.首字母大写的Undefined表示的是一种数据类型,小写的undefined表示的是属于这种数据类型的唯一的一个值.但这两种undefined都只能存在于文档或规范中,不能存在于JavaScript代码中.在JavaScript代码中,你看到的undefined最有可能是全局对象的一个属性,该属性的初始值是就是前面所说的原始值undefined,还有种情况就是,这个undefined是个局部变量,就像其他普通变量一样,没有任何特殊性,它的值不一定是undefined,但通常情况下都是的.下面我们所说的undefined,都指的是window.undefined这个属性.

    在ES3中(Firefox4之前),window.undefined就是一个普通的属性,你完全可以把它的值改变成为任意的真值,但在ES5中((Firefox4之后),window.undefined成了一个不可写,不可配置的数据属性,它的值永远是undefined.

    一个未初始化的变量的值为undefined,一个没有传入实参的形参变量的值为undefined,如果一个函数什么都不返回,则该函数默认返回undefined.

    你可以使用严格相等运算符来判断一个值是否是undefined:

    var foo;
    console.log(foo === undefined);//true
    console.log(typeof foo === 'undefined');//true
    console.log(window.foo === undefined);//true
    
    console.log(bar === undefined);//Uncaught ReferenceError: bar is not defined
    console.log(typeof bar === 'undefined');//true
    console.log(window.bar === undefined);//true
    
    console.log(typeof undefined == 'undefined'); //true
    console.log(typeof null == 'object');//true
    console.log(null == undefined);//true
    console.log(null === undefined);//false

    总结

    • Null的值是null,表示一个空对象指针,没有指向任何对象
    • Undefined的值是undefined,表示申明变量或对象的属性却未初始化
    • undefined值是派生自null的,所以对他们执行相等测试会返回true
    • 数值、布尔值、对象和字符串值都有toString()方法。但nullundefined值没有这个方法

    多数情况下,调用toString()方法不必传递参数。但是,在调用数值的toString()方法时,可以传递一个参数:输出数值的基数

    var num = 10;
    alert(num.toString());      //"10"
    alert(num.toString(2));     //"1010"
    alert(num.toString(8));     //"12"
    alert(num.toString(10));    //"10"
    alert(num.toString(16));    //"a"
    

    在不知道要转换的值是不是nullundefined的情况下,还可以使用转型函数String(),这个函数能够将任何类型的值转换为字符串。String()函数遵循下列转换规则:

      ● 如果值有toString()方法,则调用该方法(没有参数)并返回相应的结果

      ● 如果值是null,则返回"null"

      ● 如果值是undefined,则返回"undefined"

    六、Object

    Javascript中一切皆Object

    // Objects
    typeof {a:1} === 'object';
    
    // 使用Array.isArray或者Object.prototype.toString.call方法可以从基本的对象中区分出数组类型
    typeof [1, 2, 4] === 'object';
    
    typeof new Date() === 'object';
    
    // 下面的容易令人迷惑,不要这样使用!
    typeof new Boolean(true) === 'object';
    typeof new Number(1) ==== 'object';
    typeof new String("abc") === 'object';
    
    // 函数
    typeof function(){} === 'function';
    typeof Math.sin === 'function';
    

    实例化一个空Object

    var o = new Object();
    var o = new Object(undefined);
    var o = new Object(null);
    var o = {};
    

    原型

    定义属性为__proto__: 值 或 "__proto__": 值 时,不会创建名为__proto__属性。如果给出的值是对象或者null,那么对象的[[Prototype]]会被设置为给出的值。(如果给出的值不是对象也不是null,那么对象的原型不会改变。)

    var obj1 = {};
    assert(Object.getPrototypeOf(obj1) === Object.prototype);
    
    var obj2 = { __proto__: null };
    assert(Object.getPrototypeOf(obj2) === null);
    
    var protoObj = {};
    var obj3 = { "__proto__": protoObj };
    assert(Object.getPrototypeOf(obj3) === protoObj);
    
    var obj4 = { __proto__: "not an object or null" };
    assert(Object.getPrototypeOf(obj4) === Object.prototype);
    assert(!obj4.hasOwnProperty("__proto__"));
    

    在对象字面值中,仅有一次变更原型的机会;多次变更原型,会被视为语法错误。

    不使用冒号记法的属性定义,不会变更对象的原型;而是和其他具有不同名字的属性一样是普通属性定义。

    var __proto__ = "variable";
    
    var obj1 = { __proto__ };
    assert(Object.getPrototypeOf(obj1) === Object.prototype);
    assert(obj1.hasOwnProperty("__proto__"));
    assert(obj1.__proto__ === "variable");
    
    var obj2 = { __proto__() { return "hello"; } };
    assert(obj2.__proto__() === "hello");
    
    var obj3 = { ["__prot" + "o__"]: 17 };
    assert(obj3.__proto__ === 17);
    

    与JSON的区别

    • JSON 只允许"property": value syntax形式的属性定义。属性名必须用双引号括起来。且属性定义不允许使用简便写法。
    • JSON中,属性的值仅允许字符串,数字,数组,true,false,或者其他JSON对象。 
    • JSON中,不允许将值设置为函数。
    •  Date 等对象,经JSON.parse()处理后,会变成字符串。
    • JSON.parse() 不会处理计算的属性名,会当做错误抛出。

    defineProperty

    Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象

    // 使用 __proto__
    Object.defineProperty(obj, "key", {
      __proto__: null, // 没有继承的属性
      value: "static"  // 没有 enumerable
                       // 没有 configurable
                       // 没有 writable
                       // 作为默认值
    });
    
    // 显式
    Object.defineProperty(obj, "key", {
      enumerable: false,
      configurable: false,
      writable: false,
      value: "static"
    });
    
    // 回收同一对象
    function withValue(value) {
      var d = withValue.d || (
        withValue.d = {
          enumerable: false,
          writable: false,
          configurable: false,
          value: null
        }
      );
      d.value = value;
      return d;
    }
    // ... 和 ...
    Object.defineProperty(obj, "key", withValue("static"));
    
    // 如果 freeze 可用, 防止代码添加
    // value, get, set, enumerable, writable, configurable
    // 到对象原型上
    (Object.freeze||Object)(Object.prototype);
    

    configurable当且仅当这个属性描述符值为 true 时,该属性可能会改变,也可能会被从相应的对象删除。默认为 false

    enumerabletrue 当且仅当该属性出现在相应的对象枚举属性中。默认为 false。

    value 与属性相关的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined

    writable true 当且仅当可能用 赋值运算符 改变与属性相关的值。默认为 false

    存取描述符同时具有以下可选键值:

    get 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。方法将返回用作属性的值。默认为 undefined
    set 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将收到作为唯一参数的新值分配给属性。默认为 undefined
    附上几个简单粗暴的校验方式
    //低版本ie中undefined变量可以被修改,所以使用void 0 获取真实的undefined值,
    var isUndefined = function(obj) {
        //or: return typeof obj === 'undefined';
        return obj === void 0;
    };
    //typeof null 的结果是"object"。
    var isNull = function(obj) {
        return obj === null;
    };
    // boolean值,number值和string值需要考虑两种情况,值为字面量时使用typeof和Object.prototype.toString能检测; 
    // 值为构造函数构建的时候需要使用Object.prototype.toString或者instanceof检测
    var isBoolean = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Boolean]';
    };
    var isNumber = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Number]';
    };
    var isString = function(obj) {
        return Object.prototype.toString.call(obj) == '[object String]';
    };
    var isNaN = function(obj) {
        return obj !== obj;
    };
    
    //typeof 操作符在引用类型的变量里能对function有效。
    var isFunction = function(obj) {
        //or:  return Object.prototype.toString.call(obj) == '[object Function]';
        return typeof obj === 'function';
    
    };
    var isDate = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Date]';
    }
    var isArray = function(obj) {
        return Object.prototype.toString.call(obj) == '[object Array]';
    }
    var isObject = function(obj) {
        //or: return obj === Object(obj);
        return Object.prototype.toString.call(obj) == '[object Object]';
    }
    var isRegExp = function(obj) {
        //or: return obj === Object(obj);
        return Object.prototype.toString.call(obj) == '[object RegExp]';
    }
    
    var has = function(obj, key) {
        return Object.prototype.hasOwnProperty.call(obj, key);
    };
    //判断数组,字符串,对象是否为空
    var isEmpty = function(obj) {
        if (obj == null) return true;
        if (isArray(obj) || isString(obj)) return obj.length === 0;
        for (var key in obj) if (has(obj, key)) return false;
        return true;
    };
    

    原理:在任何值上调用Object原生的toString() 方法,都会返回一个[object NativeConstructorName] 格式的字符串。每个类在内部都有一个[ [Class] ]属性,这个属性就指定了上述字符串中的构造函数名NativeConstructorName

    参考来源

    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects

  • 相关阅读:
    02 Filter过滤器
    Vue入门
    Git教程
    Markdown 常用语言关键字
    王爽《汇编语言》(第三版)实验16解析
    王爽《汇编语言》(第三版)实验15解析
    王爽《汇编语言》(第三版)实验14解析
    王爽《汇编语言》(第三版)实验13解析
    王爽《汇编语言》(第三版)实验12解析
    王爽《汇编语言》(第三版)实验11解析
  • 原文地址:https://www.cnblogs.com/chenpingzhao/p/4888787.html
Copyright © 2011-2022 走看看