JavaScript-数据类型

一、简介

  • 数值:整数和小数
  • 字符串:文本
  • 布尔值:true和false
  • undefined:未定义或不存在
  • null:空值
  • 对象:各种值组成的集合

二、null和undefined

/*
null:转成数值是0
undefined转换数值是NAN
*/

// 变量声明了,但没有赋值
var i;
i // undefined

// 调用函数时,应该提供的参数没有提供,该参数等于 undefined
function f(x) {
  return x;
}
f() // undefined

// 对象没有赋值的属性
var  o = new Object();
o.p // undefined

// 函数没有返回值时,默认返回 undefined
function f() {}
f() // undefined

三、布尔值

布尔值为false的六种情况:undefined,null,false,0,NAN,""(空字符串),其它情况都是真

四、数值

JavaScript内部,所有数字都是以64位浮点数形式储存,整数也是一样

1 === 1.0  //true

由于浮点数不是精确的值,所以涉及小鼠的比较和运算要特别小心。

0.1+0.2===0.3   //false
0.3/0.1       // 2.99999999999
(0.3-0.2) === (0.2-0.1)   // false
  • NAN:是JavaScript的特殊值,表示"非数字",主要出现在将字符串解析成数字出错的场合

    s-"x"   // NAN(Not A Number)
    0/0     //NAN
    
  • 注意NAN不是一种数据类型,是一个值,它的数据类型依然是Number

    typeof NAN  // 'number'
    
  • NAN不等于任何值,包括它本身

    NAN === NAN    // false
    
  • NAN与任何数(包括它自己)的运算,得到的结果都是NAN

    NAN+11  // NAN
    NAN+22  // NAN
    NAN+NAN // NAN
    

Infinity 表示无穷,-infinity表示负无穷

与数值相关的全局方法

  • parseint:将字符串转换为整数,如果头部有空格会自动帮忙去除

    parseint("   123")    // 123
    parseint(1.23)        // 1
    
    // 字符串转换为整数的时候,是一个一个字符一次转换,如果不能转换了,就返回之前转好的部分
    parseint("123adasd")  // 123
    parseint("asdasd")
    
    // 进制转换
    parseint("1000");
    parseint("1000",10)      // 两者都是1000
    
    parseint("1000",2)    //8
    parseint("1000",6)    // 216
    
  • parsefloat:将一个字符串转为浮点数

  • isNAN:用来判断一个值是否为NAN,返回值为布尔

    isNAN(123)     //false
    isNAN("zhuyu") //true
    
  • isFinite : 返回一个布尔值,表示某个值是否为正常的数值

五、字符串

  • 定义

    var str = 'a
    b
    c';
    // 上面这样的表示方法,是会报错的,改为下面这种
    var str = 'a
    b
    c';
    // 使用 + 号进行字符串的拼接
    var name = "zhu" + "yu";
    
  • 字符串与数组

    var str = "zhuyu";
    str[0] // "z"
    str[1] // "h"
    // 可以通过索引(下标)取值
    
    str[10] //undefined,索引值超过了str字符串的最大索引值,返回undefined
    
    // 字符串不能和数组那样,对元素进行增删改
    
  • length属性:返回字符串的长度

    var name = "zhuyu";
    name.lenght // 5
    

六、对象:对象(object)是JavaScript语言的核心概念,也是最重要的数据类型

  • 生成方法

    var obj = {
        foo : "hello",
        bar : "world"
    }
    
  • 键名:对象的所有键名都是字符串,所以加不加引号都可以

    var obj = {
        foo:"hello",
        bar:"world"
    }
    
    // 如果键名是数值,会自动转换为字符串
    var objj = {
        1:"a",
        2:"b"
    }
    
  • 对象的引用

    如果不同的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址,修改其中一个变量,会影响到其他所有变量。

    var o1 = {};
    var o2 = o1;
    
    o2.name = "zhuyu";
    console.log(o1.name);    // zhuyu
    
    o1.age = 22;
    console.log(o2.age);     // 22
    
  • 属性操作:

    1. 读取对象属性有两种方法,以是.运算符,一种是方括号运算符

      var obj = {
          name:"zhuyu"
      }
      obj.name;   // zhuyu
      objp[name]; // zhuyu
      
      // 注意:数值键名不能使用.运算符,只能使用方括号运算符
      var aa = {
          1:"one"
      }
      aa.1;  // 报错
      aa[1]; // one
      
    2. 属性赋值

      var obj = {
          name:"zhuyu"
      };
      obj.age = 22;
      obj["sex"] = "男";
      
    3. 属性的查看

      var obj = {
          name:"zhuyu",
          age:22
      }
      Object.keys(obj);  // ["name","age"]
      
    4. 属性的删除

      var obj = {
          name:"zhuyu"
      }
      delete obj.name;
      // 注意删除一个不存在的键值,是不会报错的,返回值为True
      
    5. 属性是否存在:in运算符

      var obj = {
          name :"zhuyu"
      }
      "name" in obj;  //true
      "toString" in obj;  //true  结果是true,说明该属性存在,应该默认继承类中有这个属性
      
      // hasOwnProperty对象方法可以判断自身是否有什么属性
      
    6. 属性的遍历:for...in循环

      var obj = {
          a:1,
          b:2,
          c:3
      }
      for (var i in obj) {
          // i 就是键名
          console.log("键名:",i);
          console.log("键值:",obj[i]);
      }
      

      for...in 循环有两个使用注意点:

      • 它是遍历对象所有可以遍历的属性,会跳过不可遍历的属性
      • 它不仅遍历对象自身的属性,还可以遍历继承的属性
      // 只想遍历对象本身的属性
      var person = {
          name:"朱春宇"
      }
      for (key in person) {
          if (person.hasOwnProperty(key)) {
              console.log(key);
          }
      }
      
  • with 语句 : 操作同一个对象的多个属性时,提供一些书写的方便

    with 语句的格式如下

    with (对象) {
        语句;
    }
    
    var aa = {
        a1:1,
        a2:2
    }
    with (aa) {
        a1 = 11;
        a2 = 22;
    }
    // 等同于
    aa.a1 = 11;
    aa.a2 = 22;
    

    注意:with区域内部赋值操作,必须时对象已有的属性,否则会在当前作用域创建一个全局变量

    var aa = {};  // 一个空对象
    with (aa) {
        name = "zhuyu";
        age = 22;
    }
    aa.name;	// 
    name;        // zhuyu
    

七、函数:函数是一段可以反复调用的代码块。

  • JavaScript有三种声明函数的方法

    1. function命令

      function print(str) {
          console.log(str);
      }
      
    2. 函数的表示式

      var print = function(str) {
          console.log(str);    
      }
      // 上面这种声明方式,function后不能带有函数名,如果加上了,那么该函数名只有在函数体内部有效,在函数外部是无效的。
      
      var print = function f () {
          console.log(typeof f);
      }
      f;  // f is not undefined;
      print(); // function
      
    3. Function构造函数

      var print = new Function(
      	"x",
          "return x";
      )
      
  • 函数的重复声明:同一个函数被多次声明,后面的声明就会覆盖前面的声明

    function f () {
        console.log(1);
    };
    function f () {
        console.log(2);
    };
    
    f(); // 2
    
  • 圆括号运算符,return语句和递归

    1. ():调用函数,参数写在括号里
    2. return:函数的返回值,不会再执行该函数的其他代码
    3. 函数里还可以调用函数本身,但是必须要有一个结束的标志,不然会无限循环
  • 第一公民

    function add(x, y) {
      return x + y;
    }
    
    // 将函数赋值给一个变量
    var operator = add;
    
    // 将函数作为参数和返回值
    function a(op){
      return op;
    }
    a(add)(1, 1)
    // 2
    
  • 函数名的提升

    JavaScript引擎将函数名同视为变量名,也有函数名的提升

    f();
    function f () {
        console.log(1);
    }
    
    ------------------------------
    
    var f = function () {
      console.log('1');
    };
    
    function f() {
      console.log('2');
    };
    
    f(); // 1
    
  • 函数的属性属性和方法

    1. name属性:获取函数的名字

      function f () {};
      f.name;  // f1
      ----------------------------
      var f2 = function () {};
      f2.name; // f2
      ----------------------------
      var f3 = function func () {};
      f3.name; // func
      
    2. length属性:返回函数参数的个数

      function f (a,b) {};
      f.length;  // 2
      

      length属性提供了一种机制,判断定义时和调用时参数的差异,以便实现面向对象编程的方法"方法重载"(overload)。

    3. toString:返回字符串,内容时函数的源码

      function f () {
          console.log("1");
      }
      f.toString();
      /*
      function f () {
          console.log("1");
      }
      */
      
  • 函数作用域

    1. 作用域指的是变量存在的范围。ES5中,JavaScript只有两种作用域,全局作用域,局部作用域

      全局作用域:函数外部声明的全局变量
      局部作用域:函数内部定义变量的一块空间
      
    2. 函数内部的变量提升

      与全局作用域一样,函数作用域内部也会产生"变量提升"现象。var命令声明的变量。不管在什么位置,变量声明都会被提升到函数体的头部

      function foo(x) {
        if (x > 100) {
          var tmp = x - 100;
        }
      }
      
      // 等同于
      function foo(x) {
        var tmp;
        if (x > 100) {
          tmp = x - 100;
        };
      }
      
    3. 函数本身的作用域

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

      var a = 1;
      var x = function () {
        console.log(a);
      };
      function f() {
        var a = 2;
        x();
      }
      f(); // 1
      
      --------------------------
      var x = function () {
        console.log(a);
      };
      function y(f) {
        var a = 2;
        f();
      }
      y(x)
      // ReferenceError: a is not defined
      
      --------------------------
      function foo() {
        var x = 1;
        function bar() {
          console.log(x);
        }
        return bar;
      }
      var x = 2;
      var f = foo();
      f() // 1
      
  • 参数

    1. 概述:根据外部传递参数的不同,得到的返回值也不同

      function add (x,y) {
          return x+y;
      }
      add(1,2);          // 3
      add(11,22);		  // 33
      
    2. 参数的省略:JavaScript对函数的要求不高,你可以多传,也可以不传

      function print (a,b) {
          return a;
      };
      print(1,2,3);  // 1
      print(1);      // 1
      print();       // undefined
      
    3. 参数传递方式

      函数参数如果时原始类型的值(数值,字符串,布尔值),传递方式为值传递

      var name = "zhuyu";
      function setName (str) {
          str = "zhanghao";
      };
      setName(name);
      name;       // zhuyu
      

      函数参数是复合类型的值(数值,对象,其他函数),传递方式为址传递(也就是内存地址)

      var obj = {
          name:"zhuyu"
      }
      function setName (obj) {
          obj.name = "zhanghao";
      };
      setName(obj);
      obj.name;  // zhanghao
      
      ----------------------------
      
      var obj = [2,4,6]
      function setName (obj) {
          obj = [1,2,3]
      };
      setName(obj);
      obj;  // [2,4,6]
      /*
      解析上面这段代码,函数里的参数obj,在开始对应的是[2,4,6]对应的内存地址,再执行obj=[1,2,3],它是将[1,2,3]的内存地址赋值给它了,并没有改变[2,4,6]的值,所以函数执行完毕,obj这个变量对应的内存地址是没有改变的。
      */
      
    4. 同名参数

      function f (a,a) {
          console.log(a);
      }
      f(1,3);  // 3
      
    5. arguments对象

      由于JavaScript允许函数有不定数的参数,所以需要一种机制,可以在函数体内部地区所有参数。这就是argument对象的由来

      function f (args) {
          console.log(argument[0]);
          console.log(argument[1]);
      };
      f(1,2);   // 1,2
      

      正常模式下,是可以改变argument对象内部的值

      function add (a,b) {
          argument[0] = 5;
          argument[1] = 5;
          retuen a+b
      };
      add(1,1);   // 10
      

      严格模式下,修改argument对象内部值,是不会影响实际参数传递

      function add (a,b) {
          "use strict"; // 开启严格模式
          argument[0] = 5;
          argument[1] = 5;
          retuen a+b
      };
      add(1,1);   // 2
      

      通过对象argumentlength属性,可以判断函数调用时到底带了几个参数

      function f () {
          return argument.length;
      };
      f(1,2,3,4);  // 4
      f();         // 0
      
  • 函数的其他知识点

    1. 闭包:JavaScript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现

      理解闭包,首先必须要理解变量作用域,函数内部可以直接读取全局变量的

      var n = 123;
      function f () {
          console.log(n);
      }
      f();  // 123
      

      写一个实现闭包的例子

      function aa () {
          var name = "zhuyu";
          function bb () {
              console.log(name);
          }
          return bb;
      }
      var bb = aa();
      bb();  // zhuyu
      

      闭包的最大用处有两个,一个时可以读取内部的变量,另一个就是让这些变量始终保存在内存中,即闭包可以使得它诞生环境一直在。

      // 闭包使得内部变量记住上一次调用时的运算结果。
      function createIncrementor(start) {
        return function () {
          return start++;
        };
      }
      
      var inc = createIncrementor(5);
      
      inc() // 5
      inc() // 6
      inc() // 7
      
      // 闭包的另一个用处,是封装对象的私有属性和私有方法。
      function Person(name) {
        var _age;
        function setAge(n) {
          _age = n;
        }
        function getAge() {
          return _age;
        }
      
        return {
          name: name,
          getAge: getAge,
          setAge: setAge
        };
      }
      
      var p1 = Person('张三');
      p1.setAge(25);
      p1.getAge() // 25
      
    2. 立即调用的函数表达式

      (function () {}());
      
  • eval命令

    1. 基本用法:eval命令接受一个字符串作为参数,并将这个字符串党委语句执行

      eval("var a= 1;");
      a; // 1
      

      参数字符串无法当作语句运行,就会报错

      eval("3x");  // 语法错误
      

      eval没有自己的作用域,都在当前作用域执行,可能会更改当前作用域的变量

      var a = 1;
      eval("a = 2");
      a; // 2
      

      为了防止这种风险,JavaScript规定,如果使用严格模式,eval内部声明的变量,不会影响到外部的作用域

      (function f() {
          "use strict";
          eval("var foo = 123");
          console.log(foo);     // undefined;
      })
      

      不过在严格模式下,eval依然可以读写当前作用域的变量

      (function f() {
        'use strict';
        var foo = 1;
        eval('foo = 2');
        console.log(foo);  // 2
      })()
      

      总之,eval的本质是在当前作用域之中,注入代码,一般不推荐使用,最常见的地方是解析JSON数据的字符串,不过正确的做法还是JSON.parse方法。

八、数组:是按次序排列的一组值,每个值的位置都是有编号(从0开始),用[]表示

  • 定义数组

    var arr = [1,2,3];
    var arr2 = [{"name":"zhuyu"},[1,2,3],function(){return true}]
    
  • 数组的本质:属于一种特殊的对象,typeof返回的类型是object

    typeof [1,2];    // object
    
    var arr = ["a","b","c"];
    object.keys(arr);     // ["0","1","2"]
    

    JavaScript规定对象的键名必须是字符串

    var arr = [1,2];
    arr[0];   // 1
    arr["0"]; // 1
    
    // 这是因为被自动转换成了字符串
    
  • length属性:返回数组的成员个数

    ["a","b","c"].length  // 3
    

    length属性是可写的,如果人为设置一个小于当前成员的个数,那么数组会自动减少到设置length的值

    var arr = ["a","b","c","d"];
    arr.length;  // 4
    
    arr.length = 2;
    arr;         // ["a","b"]
    
    arr.length = 100;
    arr[80];     // undefined
    

    清空数组的方法:arr.length=0;

    数组也是一种特殊的对象,可以为它添加属性,不会影响到length的长度

    var arr = [];
    arr["name"] = "zhuyu";
    arr.length;  // 0
    arr["age"] = 23;
    arr.length;  // 0
    
  • in运算符:检测某个键名是否存在,适用于对象,也适用于数组

  • for...in :遍历整个数组

    var arr = ["a","b","c"];
    arr["name"] = "zhuyu";
    for (var i in arr) {
        console.log(i);
    }
    // 输出效果为 0,1,2,name
    
  • 数组的空位:数组的某个元素是空元素,即两个逗号之间没有任何值

    var a = [1,,1];
    a.length; // 输出为3
    
    a[1];     // undefined
    

    使用delete命令删除一个数组成员,会形成空位,并且不会影响lenght属性

    var arr = [1,2,3];
    delete arr[0];
    arr.length;  // 3
    arr[0];      // undefined
    
  • 类似数组的对象

    如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,称为"类数组对象"。

原文地址:https://www.cnblogs.com/zhuchunyu/p/10648643.html