数据类型包括:基础类型和引用类型。
- 在ES5之前,基础类型有:Number,String ,Boolean, Undefined, Null; 而在ES6中,又增加了Symbol这种基础类型。
- 引用类型包括:Object,Array,Function,Date,RegExp,特殊的包装类型Number、String、Boolean,以及单体内置对象Global和Math
- 基础类型都被存储在栈内存中,而引用类型被存储在堆内存中。
引用类型
小记:所有对象都有toString(),toLocalString(),valueOf()方法;
toString和toLocalString的区别是:
- 在数字超过3位数时,toLocalstring可以加上千位分隔符;
- 在转换日期类型时,有区别。
var a = 1234;
a.toString(); // '1234'
a.toLocalString(); // '1,234'
var d = new Date();
d.toString(); // "Wed Mar 18 2020 23:17:51 GMT+0800 (中国标准时间)"
d.toLocaleString(); // "2020/3/18 下午11:17:51"
1. Object
两种创建的方式,new 构造函数和对象字面量;且使用对象字面量创建时,不会调用构造函数;
2. Array
- 两种创建的方式,new 构造函数和对象字面量;且使用对象字面量创建时,不会调用构造函数;
- 可以通过修改数组的length,来修改数组的长度和内容。
- 数组的检测,使用instanceof 和 Array.isArray(),constructor(看数组的构造函数是否是Array);
- toString() 和 join()的区别,前者只能转换成以逗号分隔的字符串,而后者默认是逗号,也可以添加任意的符号;
- 栈方法:push,pop
// 可以看出,push返回的是数组的长度,而pop则返回最后一项的值
var color = new Array();
color.push('red','green'); // 2
color.push('red','green'); // 4
color.pop(); // "green"
- 队列方法:shift,unshift
// 与栈方法类似,添加的返回长度,而减少的返回第一项的值
var list = new Array();
list.unshift('123'); // 1
list.unshift('123','123','23'); //4
list.shift('123'); // "123"
- 排序方法:reverse,sort
reverse是反转方法;
而sort是排序方法,默认升序排序,只不过是按照字符串排序的,所以一般会使用排序函数作为函数; - 操作方法:concat,slice,splice
splice 可以做数组的插入,修改,删除,参数(index, num, 新增的值1,新增值2)
slice 是以原数组为准生成一个新数组,可以传入参数start,end;它可以返回一个新的数组,但不是真正意义上的深拷贝,只能深拷贝1层,第二层的时候,没能拷贝成功。
var arr = [1,2,3]
var brr = arr.slice()
arr.push(33)
console.log(arr); // (4) [1, 2, 3, 33]
console.log(brr); // (3) [1, 2, 3]
// slice拷贝一层
var arr = [1,2,[0,0]];
var arr2 = arr.slice();
// 修改第一层
arr2[0] = 3;
arr; // [1,2,[0,0]]
arr2; // [3,2,[0,0]]
// 修改第二层
arr2[2][0] = 1
arr2; // [3,2,[1,0]]
arr; // [1,2,[1,0]]
- 位置方法: indexOf, lastIndexOf、find(callback)、findIndex(callback), includes</br>
其中,indexOf,lastIndexOf,includes都参数都是要搜索的元素,而find和findIndex,则用函数做参数
// find和findIndex的回调函数的参数分别是:当前值,当前索引,原始数组
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2
// 另外find和findIndex还可以接受第二个参数,用于绑定回调函数this
function f(v){
return v > this.age;
}
let person = {name: 'John', age: 20};
[10, 12, 26, 15].find(f, person); // 26
- 迭代方法:every,some,filter,forEach, map
every 不会对空数组做检测,默认返回true;
var a = new Array(3); // a 是空数组
a.every(function(item, index, array){})
every和some的区别: every是数组中的每一项都满足条件才返回true,而some是只要有一项满足就返回true
var arr = [1,2,3,4,5,6];
arr.every(function(item,index,array){return item > 2}); // false
arr.some(function(item,index,array){return item > 2}); //true
filter是过滤后返回一个新数组
var arr = [1,2,3,4,5,6];
arr.filter((item, index, array)=>{return (item > 4)}); // [5,6]
map也会返回一个新数组,每一项是在原有的项上操作后的结果
var arr = [1,2,3,4,5,6];
arr.map((item, index, array)=>{return item + '*map'}); // ["1*map", "2*map", "3*map", "4*map", "5*map", "6*map"]
map和flatmap,其实map就是deep为1的flatmap
var arr1 = [1, 2, 3, 4];
arr1.map(x => [x * 2]);
// [[2], [4], [6], [8]]
arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]
// only one level is flattened
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]
- 归并方法:reduce,reduceRight
// 归并求数组所有值的和
var arr = [1,2,3,4,5];
var sum = arr.reduce(function(prev, cur, index, arr){
console.log(prev,cur);
return prev+cur;
})
// 输出
1 2
3 3
6 4
10 5
// sum = 15
- 稀疏数组:数组中有undefined
// 稀疏数组
arr.index('undefined') === -1 && arr.includes('undefined') === true
说明arr是稀疏数组
3. Date
var dd = new Date();
dd.valueOf(); // 1584547427750; 返回毫秒数,可以做日期比较
dd.toDateString(); // "Thu Mar 19 2020"
dd.toString(); // "Thu Mar 19 2020 00:03:47 GMT+0800 (中国标准时间)"
dd.toLocaleString(); // "2020/3/19 上午12:03:47"
dd.toTimeString(); // "00:03:47 GMT+0800 (中国标准时间)"
dd.toUTCString(); // "Wed, 18 Mar 2020 16:03:47 GMT"
4. RegExp
-
RegExp的方法有test, exec, compile,
其中test返回true和false,而exec返回匹配的字符串,要注意的是,exec加上了g(全局标志)之后,执行依次返回字符串 -
支持正则表达式的String对象的方法:match、replace、split、search
5. Function
函数实际上是对象,因为函数名实际上是指向某个函数的指针,不会与某个函数绑定。
==内容较多,具体见Function介绍==
6. 基本包装类型
基本包装类型包括Number,String,Boolean。它们与其他引用类型相似,但同时具有各自对应的基本类型的特殊行为。
(1)共同点
- 实际上,每当读取一个基本类型的值时,后台就会创建一个对应的基本包装类型的对象,从而让我们能都调用一些方法来操作它们。
// 以String为例
var s1 = 'love and peace';
var s2 = s1.substring();
// 实际上等价于
var s1 = new String('love and peace');
s2 = s1.substring();
s1 = null;
为了让我们有更直观的操作,其实后台做了如下操作:
(1)创建String类型的一个实例;
(2)在实例上调用指定的方法;
(3)销毁这个实例
因为引用类型和基本包装类型的主要区别是对象的生存期不同。使用new创建的引用类型实例,在执行流离开当前作用域之前,一直保存在内存中,而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁,这就是为什么我们不能给基本类型添加属性和方法的原因。
var s1 = 'some colors';
s1.color = 'red';
console.log(s1.color); // undefined
// 原因是第二行创建的String对象,在执行第三行时,已经被销毁了,而第三行代码又创建了自己的String对象,此时对象是没有color属性的。
- 用new调用基本包装类型的构造函数,与直接写基本类型的数据类型是不一样的。
var a = 1234;
typeof a; // "number"
var a2 = new Number(1234);
typeof a2; // "object"
a2 instanceof Number; // true
-------------------------------
var s = 'rreerew'
typeof s; // "string"
var s2 = new String();
typeof s2; // "object"
s2 instanceof String; // true
-------------------------------
var b = true;
typeof b; // "boolean"
var b2 = new Boolean(false)
typeof b2; // "object"
b2 instanceof Boolean; // true
b2; // Boolean {false}__proto__: Boolean[[PrimitiveValue]]: false
b2 && true; // true,因用基本包装类型创建的对象,都会被转换成true
不同点
- 尽量少用Number和Boolean的基本包装类型
- Number类型的方法
- toFixed(),
toExponential(指数表示法);
toPrecision(固定大小)
- toFixed(),
var n = 99;
n.toPrecision(1); // "1e+2"
n.toPrecision(2); // "99"
n.toPrecision(3); // "99.0"
- String的方法
(1)字符串操作:charAt(), charCodeAt(),数字索引
var str = 'love and peace';
str.charAt(1); // "o"
str.charCodeAt(1); // 111,返回字符编码ASCII码
str[1]; // "o" 仅ES5以上支持
(2)==字符串操作方法== concat、substr、slice、substring
concat就是字符串拼接;
substr、slice、substring都是返回一个新的字符串,它们的区别如下:
// 这三个方法都可以返回一个新的字符串,如果不传任何参数,就相当于复制了一个字符串;
// 同时这三个参数都支持两个参数,substring和slice都是start和end索引; 而substr是start索引和返回的字符个数number;
var str = 'love and peace';
---------------------------------
// 如果是同一个参数,三个都是一样的
str.slice(3); // "e and peace"
str.substring(3); // "e and peace"
str.substr(3); // "e and peace"
----------------------------------
// 加了第二个参数,substr和另外两个不一样
str.slice(3,7); // "e an"
str.substring(3,7); // "e an"
str.substr(3,7); // "e and p"
--------------------------------
// 如果参数里有负数,区别较大
// slice是把负数与字符串长度相加,str.length = 14;
// substring 会把所有负数都转为0;
// substr
str.slice(3,-4); // "e and p" 提取出index从3~10的字符串
str.substring(3,-4);//"lov" 提取出3~14;
str.substr(3,-4); // "" 第二个参数为负数,个数为负数,转换为0
str.substr(-3); // 'ace' 从index为11开始
(3)字符串位置indexOf,lastIndexOf
可以传两个参数,第一个参数是索引,第二个参数是要查找的==子字符串==;区别是indexOf从头开始找,而lastIndexOf从尾巴开始找。
(4)trim去掉字符串收尾的空格
(5)大小写转换:
var str = 'love and peace';
str.toLocaleUpperCase(); // "LOVE AND PEACE"
str.toUpperCase(); // "LOVE AND PEACE"
var str = 'ASCII';
str.toLocaleLowerCase(); // "ascii"
str.toLowerCase(); // "ascii"
// 区别: 带有Locale的表示是针对地区的方法,可以根据少数语言做特殊类型
(6)匹配方法
match、replace、search、split
var mobile = '17700001111';
mobile.match(/\d/); // ["1", index: 0, input: "17700001111", groups: undefined]
mobile.match(/\d/g); // (11) ["1", "7", "7", "0", "0", "0", "0", "1", "1", "1", "1"]0: "1"1: "7"2: "7"3: "0"4: "0"5: "0"6: "0"7: "1"8: "1"9: "1"10: "1"length: 11__proto__: Array(0)
mobile.search(/[0]/); // 3
mobile.search(/[0]/g); // 3
-------------------------------------------------
var dd = '1#2#'
dd.split(/\#/); // (3) ["1", "2", ""]
-------------------------------------------------
var mobile = '17700001111';
mobile.replace(/\d/g, 'abc'); // "abcabcabcabcabcabcabcabcabcabcabc"
mobile.replace(/\d/g, '#'); // "###########"
// replace的第二个参数也可以是Function
function htmlEscape(text) {
return text.replace(/[<>"&]/g, function(match, pos, originalText){
switch(match) {
case "<":
return '<';
case ">":
return '>';
case "\":
return '"';
case "&":
return '&'
}
})
}
var str = '<p class=\"greet\">hello world</p>'
htmlEscape(str); // "<p class="greet">hello world</p>"
(7)localCompare:比较两个字符串的排序
// 前面出现的返回1,后面出现的返回0,比较的是全部字母,只有完全相等时返回0
var str = 'hello'
str.localeCompare('yellow'); // -1
str.localeCompare('world'); // -1
str.localeCompare('hebe'); // 1
str.localeCompare('hellw'); // -1
str.localeCompare('hella'); // 1
str.localeCompare('hello'); // 0
str.localeCompare('abc'); // 1
(8)fromCharCode:与charCodeAt相反,这个是通过字符串编码转换成字符
7. 单体内置对象
Global和Math
- 不能直接访问Global对象,但是它有一个可以指代的对象window,即Global中的方法,都可以在window中访问得到;
- isNaN,isInfinite,parseInt,parseFloat都是Global对象的方法;
- eval函数;参数中的字符串到函数运行,被执行的代码具有与执行环境相同的作用域(即作用域和eval所在的相同);
var str = 'hello world'
eval('alert(str)')
- 常用的encodeURI和decodeURI、encodeURIComponent和dncodeURIComponent,可以直接调用,它们就是属于Global中的,且经常使用的是encodeURIComponent和dncodeURIComponent,因为它们可以转换整个URI;
// 区别一目了然
let url = "https://www.baidu.com?arg=100 arg=200";
encodeURIComponent(url); // "https%3A%2F%2Fwww.baidu.com%3Farg%3D100%20arg%3D200"
encodeURI(url); // "https://www.baidu.com?arg=100%20arg=200"
- Math常用的方法,Math.floor()、Math.ceil()、Math.min()、Math.max()、Math.random()。都较简单,不做介绍。
// 用Math.max和apply实现求得数组中的最大值;
var arr = [1,14,4,5,99,-1];
Math.max.apply(Math, arr); // 99
Math.min.apply(Math, arr); // -1
网友评论