数据类型
分类 | 详细类型 | |||
原始类型 | 数字(Number) | |||
字符串(String) | ||||
布尔型(Boolean) | ||||
null | ||||
undefined | ||||
引用类型 | 对象(object) | |||
函数(Function)特殊的引用 | ||||
数组(Array) |
1.null和undefined的区别
null表示一个对象不存在,即“没有对象”;undefined表示基本类型或对象的值没被定义
typeof undefined; //undefined
typeof null; //object
Number(undefined); //NaN
Number(null); //0
null当使用完一个比较大的对象时,需要对其进行释放内存时,设置为null;
let a = [1,2,3];
a = null; //用来清除a引用的数据
2.Infinity和NaN
两者都是Number类型
类型 | 相同点 | 例子 | 说明 |
Infinity | 都是Number类型 | 2/0 | 表示无限大,超过JS的number所能够表示的最大值。 |
NaN | 0/0 | 表示not a number,无法计算的结果。 |
NaN
这个特殊的Number与所有其他值都不相等,包括它自己: NaN === NaN; //false
3.数组
数组中可以包含任意类型:
[1, 2, 3.14, 'Hello', null, true]
4.strict
js不强制要求用var
申明变量。这个设计错误带来了严重的后果:如果一个变量没有通过var
申明就被使用,那么该变量就自动被申明为全局变量:
i = 10;
使用var
申明的变量则不是全局变量,它的范围被限制在该变量被申明的函数体内,同名变量在不同的函数体内互不冲突。
为了修补JavaScript这一严重设计缺陷,ECMA在后续规范中推出了strict模式,在strict模式下运行的JavaScript代码,强制通过var
申明变量,未使用var
申明变量就使用的,将导致运行错误。
启用strict模式的方法是在JavaScript代码的第一行写上:
'use strict';
5.String类型相关操作
var str = 'Hello Word';
str.toUpperCase(); //'HELLO WORD'
str.toLowerCase(); //'hello word'
str.indexOf('Word'); //6
str.substring(6); //'Word'
str.substring(1,5); //'ello'
6.数组操作
var arr = new Array(1,2,3);
arr.length; //3
//若直接给arr设置length,则会改变arr
arr.length = 5; //arr = [1,2,3,undefined,undefined]
//array也没有越界的概念,可以直接赋值给越界的索引
arr[6] = 100; //arr = [1,2,3,undefined,undefined,undefined,6]
//indexOf,返回索引;若不存在,返回-1;
let array = [1,2,3];
array.indexOf(2); //1
array.indexOf(5); //-1
//slice, 返回一个新数组
let arr = [1,2,3];
let arr1 = arr.slice(); //返回一个新的一样的数组
//splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 从索引2开始删除3个元素,然后再添加两个元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回删除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只删除,不添加:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只添加,不删除:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因为没有删除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
//join()方法,用于连接数组元素
let arr = [1,2,3,a];
arr.join('-'); //'1-2-3-a';
//concat()方法 返回一个新的数组!!!
let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr = arr1.concat(arr1);
上面的操作可以用ES6的操作代替:
let arr = [...arr1, ...arr2]
7.Object(对象)
//对象属性的删除添加
let person = {
name: 'zhangsan'
};
person.age = 18; //添加age属性
delete person.age; //删除age属性
//delete person[age]; 也可以这样删除
//如果要查看对象是否有某一属性,可以用'in'操作符,但是继承的属性,也会被检测出来
var person = {
name: 'zhangsan',
};
'name' in person; // true
'grade' in person; // false
'toString' in person; //true
//要判断属性是不是对象自身拥有的,可以用hasOwnProperty()方法:
person.hasOwnProperty('name'); //true
person.hasOwnProperty('toString'); //false
8.ES6新增的Map、Set和Array.from()方法
1.Map
Map映射是ES6里面新增的一个对象,是一组键值对的结构,具有极快的查找速度。初始化Map需要一个二维数组,或者直接初始化一个空Map
let m1 = new Map([[a,'a1'],[b, 'b1'],[c, 'c1']]);
let m2 = new Map([[a,'a1'],[b, 'b1'],[c, 'c1']]);
let m3 = new Map();
console.log(m1); // 返回Map {"a" => "a1", "b" => "b2", "c" => "c3"}
console.log(typeof(m1)); // object, Map仍属于 object
console.log(m1 == m2) // flase 虽然两个Map里面的值一样,但是是属于不同的object
// 1. size属性,返回 Map的元素数
console.log(m1.size); // 3
// 2. keys() 获取Map的所有key
console.log(m1.keys()); // 返回 MapIterator {"a", "b", "c"}
// 3. values() 获取Map的所有value
console.log(m1.values()); // 返回 MapIterator {"a1", "b2", "c3"}
// 4. entries() 获取Map所有成员
console.log(m1.entries()); // 返回 MapIterator {"a" => "a1", "b" => "b2", "c" => "c3"}
// 5. forEach() 循环操作映射元素
m1.forEach(function(value, key, map) {
// value: key对应的值,
// key: Map的key,(map参数已省略情况下,key可省略)
// map: Map本身,(该参数是可省略参数)
console.log(value); // key对应的值 a1 b2 c3
console.log(key); // key a b c
console.log(map); // Map本身 Map Map Map
});
// 6. set() 给Map添加数据, 返回添加后的Map
console.log(m2.set('a', 1)); // 返回Map {"a" => 1}
console.log(m2.set('b', 2)); // {"a" => 1, "b" => 2}
console.log(m2.set('a', 11)); // {"a" => 11, "b" => 2} 给已存在的键赋值会覆盖掉之前的值,
// 7. has() 检测是否存在某个key, 返回布尔值,有:true; 没有:false
console.log(m2.has('a')); // true
console.log(m2.has('c')); // false
// 8. get() 获取某个key的值,返回key对应的值,没有则返回undefined
console.log(m2.get('a')); // 11
console.log(m2.get('c')); // undefined
// 9. delete() 删除某个key及其对应的value,返回布尔值,成功:true; 失败:false
console.log(m2.delete('b')); // true
console.log(m2.delete('d')); // false
console.log(m2.get('b')); // undefined, 因为b已经删除
// 10. clear() 清除所有的值,返回 undefined
console.log(m1.clear()); // undefined
console.log(m1);
2.Set
初始化Set需要提供一个Array作为输入,或者直接创建一个空Set
var s1 = new Set(['a', 'b', 'c']);
var s11 = new Set(['a', 'b', 'c']);
var s2 = new Set(['a', 'a', 'b', 'b', 'c', 'c']);
var s3 = new Set();
console.log(s1); // 返回 Set(3) {"a", "b", "c"}
console.log(s2); // 返回 Set(3) {"a", "b", "c"}
console.log(typeof(s1)); // object
console.log(s1 == s11); // false
console.log(s1 == s2); // false
// 1. size属性 返回Set的元素数
console.log(s1.size); // 3
// 2. keys() 获取Set的所有key
console.log(s1.keys()); // 返回 SetIterator {"a", "b", "c"}
// 3. values() 获取Set的值,返回结果和 keys()一样
console.log(s1.values()); // 返回 SetIterator {"a", "b", "c"}
// 4. entries() 获取Set所有成员,返回同keys()
onsole.log(s1.entries()); // 返回 SetIterator {"a", "b", "c"}
// 5. forEach() 循环操作集合元素
s1.forEach(function(v, k, s){ // v、k是集合的键,s是集合本身
console.log(v); // a b c
console.log(k); // a b c
console.log(s); // Set Set Set
});
// 6. add() 给集合添加数据 返回添加后的Set
console.log(s3.add('aa')); // Set(1) {"aa"}
console.log(s3.add('bb')); // Set(2) {"aa", "bb"}
console.log(s3.add('aa')); // Set(2) {"aa", "bb"} 添加重复的值,会被排重掉,
// 7. has() 查询集合中是否包含某个元素 返回布尔值 有:true; 没有:false
console.log(s3.has('aa')); // true
console.log(s3.has('ff')); // false
// 8. delete() 删除集合中的某个元素 返回布尔值
console.log(s3.delete('aa')); // true
console.log(s3.delete('ee')); // false
console.log(s3); // Set(1) {"bb"}
// 9. clear() 清除集合的所有值 返回undefined
console.log(s1.clear()); // undefined
console.log(s1); // Set(0) {}
//10.Set可以很方便进行数组的一些操作,Set和数组可以随意转换,如数组去重
let arr = [1,2,'a',2,3,null,undefined,null,NaN,4,5]
let b = new Set(arr); //Set(9) {1,2,'a',3,null,undefined,NaN,4,5}
//用es6的扩展运算符将其转换为数组即可
let c = [...b]; //[1,2,'a',3,null,undefined,NaN,4,5]
//或者采用Arrar.from
let d = Array.from(b); //[1,2,'a',3,null,undefined,NaN,4,5]
//11.Array.from()函数
Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。那么什么是类数组对象呢?所谓类数组对象,最基本的要求就是具有length属性的对象。
(1)将类数组对象转换为真正数组:
let arrayLike = {
0: 'tom',
1: '65',
2: '男',
3: ['jane','john','Mary'],
'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['tom','65','男',['jane','john','Mary']]
那么,如果将上面代码中length属性去掉呢?实践证明,答案会是一个长度为0的空数组。
这里将代码改一下,就是具有length属性,但是对象的属性名不再是数字类型的,而是其他字符串型的,代码如下:
let arrayLike = {
'name': 'tom',
'age': '65',
'sex': '男',
'friends': ['jane','john','Mary'],
length: 4
}
let arr = Array.from(arrayLike)
console.log(arr) // [ undefined, undefined, undefined, undefined ]
会发现结果是长度为4,元素均为undefined的数组
如果再改一下:
let arrayLike = {
0: 'tom',
3: ['jane','john','Mary'],
'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['tom',undefined,undefined,['jane','john','Mary']]
key值是数字但是不连续,空缺的部分将会为undefined。
由此可见,要将一个类数组对象转换为一个真正的数组,必须具备以下条件:
1、该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。
2、该类数组对象的属性名必须为数值型或字符串型的数字
ps: 该类数组对象的属性名可以加引号,也可以不加引号
(2)将Set结构的数据转换为真正的数组:
let arr = [12,45,97,9797,564,134,45642]
let set = new Set(arr)
console.log(Array.from(set)) // [ 12, 45, 97, 9797, 564, 134, 45642 ]
Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。如下:
let arr = [12,45,97,9797,564,134,45642]
let set = new Set(arr)
console.log(Array.from(set, item => item + 1)) // [ 13, 46, 98, 9798, 565, 135, 45643 ]
(3)将字符串转换为数组:
let str = 'hello world!';
console.log(Array.from(str)) // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"]
(4)Array.from参数是一个真正的数组:
console.log(Array.from([12,45,47,56,213,4654,154]))
像这种情况,Array.from会返回一个一模一样的新数组
9.ES6新增的iterable类型
遍历Array
可以采用下标循环,遍历Map
和Set
就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable
类型,Array
、Map
和Set
都属于iterable
类型。具有iterable
类型的集合可以通过新的for ... of
循环来遍历。
let arr = new Array(1,2,3);
let set = new Set([1,2,3,3]);
let map = new Map([['a',1],['b',2],['c',3]]);
//遍历Array
for(let e of arr){console.log(e)}; //1,2,3
//遍历Set
for(let e of set){console.log(e)}; //1,2,3
//遍历Map
for(let e of map){console.log(`${e[0]}: ${e[1]}`)}; //a:1,b:2,c:3
//for...in 和 for...of
for...in用来遍历对象,因为数组也是对象,因此,也可以比那里数组,但会有以下问题:
var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x in a) {
console.log(x); // '0', '1', '2', 'name'
}
而用for...of,则不会有这个问题,itrable类型用for...of遍历:
var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x of a) {
console.log(x); // 'A', 'B', 'C'
}
//然而,更好的方式是直接使用iterable内置的forEach方法,它接收一个函数,每次迭代就自动回调该函数
//array
var a = ['A', 'B', 'C'];
a.forEach(function (element, index, array) {
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
console.log(element + ', index = ' + index);
});
//Set
var s = new Set(['A', 'B', 'C']);
s.forEach(function (element, sameElement, set) {
console.log(element);
});
//Map
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
m.forEach(function (value, key, map) {
console.log(value);
});