Javascript是弱类型语言,统一使用var声明定义变量(在函数中如果使用var定义变量则该变量是局部变量,如果没有var只有变量名,则该变量是全局变量),要想知道变量是哪种具体类型可使用typeof返回类型字符串(number、string、boolean、undefined,function或object,其中object又可细分为日期、数组字面量、对象字面量、Map、Set、null等)。Javascript的类型主要分基本类型和对象类型两大类:

       1、基本类型:number、string、boolean、undefined。

var a=3;
var b='hello,JavaScript!';
var c=true;
var d=undefined;

           1>number:

               ①JavaScript不区分整数和浮点数,没有整型和浮点型的说法,统一用number表示。占位64位,长度和Java中的double类型长度一样;              

               ②NaN:Not a Number,表示一个不是数字的数值。NaN本身是个数值,但不等于任何值,包括它自己。可以使用isNaN()函数检测。

               ③Infinity:表示无限大,即超过了number所能表示的最大值(约1.79769313486231570e+308);

           2>string: 

               ①string类型变量用单引号或双引号括起来,发明JavaScript时Unicode是16位的字符集,所以JavaScript中所有字符都是16位;

               ②string类型中的转义字符用来把那些正常情况下不被允许的字符插入到特殊字符串中,比如反斜线、引号或控制字符。\u约定字符编码,例如"A"==="\u0041";

               ③string类型的字符串有一个length属性(注意不是方法),返回包含的字符数;

               ④最新的ES6标准新增了一种支持换行字符串的表示方法,用反引号 ` ... ` (Esc键)包围即可;

               ⑤最新的ES6标准新增反引号 ` ... ` (Esc键),被其包围的${变量名}将会自动转为变量名所代表的值;

           3>boolean:

               false、null、undefined、空字符串''以及数字0都被当成false处理,除这几个值之外的值JavaScript都当作true处理。

       2、对象类型:日期、数组字面量、对象字面量、Map、Set。

            解构赋值:从ES6开始支持解构赋值,直接对多个变量同时赋值(注意=前后的类型、嵌套层次和位置要保持一致,比如=前后要对象都是对象,要数组都是数组),例如:

var [x, y, z] = ['a', 'b', 'c'];

此时x、y、z会分别赋值为'a'、'b'、'c'。也可以忽略某些值,例如:

var [, , z] = ['a', 'b', 'c']; //忽略a,b

此时z取到了值'c'。还可以很方便从对象中获取想要的属性值,例如:

var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school'
};
var {name, age, passport} = person;

           1>日期:

       创建指定的日期时间可以使用如下几种方式:

new Date() //返回当前日期和时间
new Date(6*60*60*1000) //返回从1970年1月1日在指定毫秒数后的时间
new Date("October 13, 1975 11:13:00") //返回用字符串指定的日期和时间
new Date(2018, 9, 20, 21, 32, 59, 543); //参数顺序依次为:年月日时分秒毫秒

       可以从Date对象中获取如下信息(注意月份的范围为0~11,所以5表示6月):

var current = new Date();
current; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
current.getFullYear(); // 2015, 年份
current.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
current.getDate(); // 24, 表示24号
current.getDay(); // 3, 表示星期三
current.getHours(); // 19, 24小时制
current.getMinutes(); // 49, 分钟
current.getSeconds(); // 22, 秒
current.getMilliseconds(); // 875, 毫秒数
current.getTime(); // 1435146562875, 以number形式表示的时间戳(单位:毫秒)

       也可以解析一个符合ISO 8601格式的字符串获取以毫秒为单位的时间戳:

var d = Date.parse('2015-06-24T19:49:22.875+08:00');

           2>数组字面量:

           JavaScript没有数组这样的数据结构,但提供一种类数组的对象,它们都会连接到原型对象Array.prototype,它把数组的下标转变为字符串作为该对象的属性,这样访问该对象的属性时就像像Java一样在通过数组下标访问数组元素。由于JavaScript是弱类型语言,所以不要求数组字面量中必须是相同类型的元素。例如一个长度为7的数组,含各种类型的元素:

var array=['abc',98.6,true,null,undefined,{name:'Tom'},['fish','sheep']];

               ①数组创建可以使用

var array = [1,2,3];

也可以使用

var array = new Array(1,2,3);

但出于代码的可读性考虑,强烈建议直接使用第1种;

               ②length属性,默认是数组元素的个数,但可以随意设置该属性。当设置的length值比实际元素的个数多时不会分配更多的内存空间,但当设置的length值比实际元素的个数少时,下标大于等于length值的元素会被删除。

               ③给数组添加元素,可以使用

array[array.length]='';

或者⑤中的unshift给数组头部插入元素,或者⑥中push给数组末尾添加元素。

        其实是给数组对象添加了属性名是整数的属性值,但是如果给数组对象添加属性名不是整数的值时,比如添加array['key1']而不是array[8]时,数组属性length不会发生变化。也就是说此时不是给数组添加了元素,而是给整个数组对象添加了属性。

               ④数组删除元素,因为数组元素也是对象所以可以使用delete进行删除。

delete array[2];

       但是用delete删除之后数组的length值不变,对应的已删除的元素的值变为undefined。为了避免这种情况可以使用splice()方法进行删除。

array.splice(2,1);

此时数组的属性length值才会减1。也可使用⑤中的shift从数组头部删除元素,或者⑥中pop从数组末尾删除元素。

               ⑤unshift和shift:

       unshift给数组头部插入元素

var array = [1, 2];
array.unshift('A', 'B');

       shift从数组头部删除元素

array.shift();

               ⑥push和pop:

       push给数组尾部新增元素

var array = [1, 2];
array.push('A', 'B');

       pop从数组尾部删除元素

array.pop();

               ⑦判断是否为数组,可以使用

Object.prototype.toString.apply(array)==='[object Array]'

               ⑧数组的map高阶函数:把集合的每个元素分别调用map中指定的函数,最后返回一个结果的集合,例如:

var array = [1,2,3];
function pow(x) {
    return x * x;
}
var result = array.map(pow);//result为[1, 4, 9]

        注意如果map指定的函数参数个数>1,可能导致出现意外结果。因为map函数会自动传三个参数,分别是:element、index、array,如果指定函数参数个数>1,第二、第三个参数不是人为传入的,会出现问题,比如map指定parseInt时就会出现意外结果。

               ⑨数组的reduce高阶函数:必须有两个参数,调用reduce指定的函数后生成的结果,再与集合中下一个元素作为这个函数的两个入参调用该函数,直到集合中所有元素都已参与运算,例如:

var array = [1,2,3,4,5];
function add(x,y) {
    return x + y;
}
var result = array.reduce(add);//result为15

               ⑩数组的filter高阶函数:通过filter指定的函数返回的true和false把数组的某些元素过滤掉,然后返回剩下的元素,filter指定的函数可接受多个参数,map函数会自动传三个参数,分别是:element、index、array,但一般只使用第一个参数。用法如:

var array = [1,2,4,5,6,9,10,15];
function fil(x){
    return x%2 !== 0;
}
var result = array.filter(fil);  //[1,5,9,15]

               ⑪数组的sort高阶函数:默认把所有元素先转换为String后升序排序,数字也会先转换成String再升序排序。通常规定:对于两个元素x和y,如果x < y,则返回-1,如果x == y,则返回0,如果x > y,则返回1。根据返回的-1、0和1进行排序,如果返回-1,则排序结果将第一个参数放在第二个参数之前,否则放在第二个参数之后。例如:

var array = [5,2,4,7,1,10,3,9];
function newsort(x,y){
    if (x < y) {
        return 1;
    }
    if (x > y) {
        return -1;
    }
    return 0;
}
var result = array.sort(newsort);  //[10,9,7,5,4,3,2,1]

     sort()方法会直接对入参Array进行修改,它返回的结果仍是入参Array。

           3>对象字面量:       

       JavaScript对象字面量是属性的容器,由{}括起来的若干属性组成对象,属性名与属性值之间用冒号分隔,属性与属性之间用逗号分隔。每个对象字面量都会连接到原型对象Object.prototype,相当于Java中每个子类都会继承自一个父类,对对象修改时不会修改原型对象的属性,但对对象访问属性时会通过“委托”逐层向上查找属性,直到找到对应属性为止。

var people={id:1,name:'Tom',age:30,sex:'male','':'未知属性'};

               ①属性名是包括空字符串''在内的任意字符串,如果属性名不是空字符串和保留字,可以不用引号括起来,否则一定需要用引号括起来。

               ②属性值是除undefined之外的任何值,可以嵌套,也就是说属性值可以又是一个对象。

               ③访问对象的属性时,如果属性名必须用引号括起来,那么只能使用:对象名['属性名']访问;否则还可以使用:对象名.属性名进行访问。当然优先选择第二种方式,因为它更紧凑且可读性更好。

               ④如果尝试获取一个并不存在的属性将会返回undefined,运算符||可用来设置默认值,例如:

people.height||175    //将people对象的属性height的默认值设为175,如果获取不到该值则取175

               ⑤如果从undefined对象中获取属性会导致TypeError异常,常用的解决方案是:

if(people && people.height){
}

               ⑥给对象的属性赋值:如果该属性存在则将该属性值更改,但原型中属性不会被更改。如果该属性不存在则给该对象新增属性。

               ⑦可以使用方法:对象名.hasOwnProperty('属性名')判断该属性是否在该对象中定义,该方法不会去检查原型中的属性。

               ⑧可以使用操作符in判断属性是否在该对象中:

height in people

               ⑨对象中属性的顺序是无序的,所以通过for in循环得到的属性顺序也是不固定的。

               ⑩delete运算符可以删除对象中非原型定义的属性,如果原型中也有该属性,删除之后再访问该属性时则显示原型中定义的属性值。

           4>Map:

       JavaScript的对象字面量有个小问题,就是键必须是字符串。但实际上number或者其他数据类型作为键也是非常合理的。为了解决这个问题,最新的ES6规范引入了新的数据类型Map。

               ①创建Map对象:

var map = new Map([['key1', 11], ['key2', 22], ['key3', 33]]);

               ②给Map对象添加元素:

map.set('key4',44);

               ③判断Map对象是否存在某个key:

map.has('key1');

               ④获取Map对象某个key的值:

map.get('key1');

               ⑤删除Map对象某个key对应的元素:

map.delete('key1');

           5>Set:

       最新的ES6规范引入了新的数据类型Set。

               ①创建Set对象:重复的值被自动过滤:

var set = new Set([1, 2, 3, 3, '3']);

               ②给Set对象添加元素:

set.add(5);

               ③判断Set对象是否存在某元素:

set.has('3');

               ④删除Set对象的某个元素

set.delete('3');

 

参考:Douglas Crockford《JavaScript语言精粹》