js常用对象
基本引用类型
Date
Date和java的Date类似,里面保存的是从1970年1月1日至今的毫秒数。
创建
- Date(date): 创建一个Date对象,包含创建时的时间.date是字符串形式的时间,格式可以参照parse()的格式
- Date.now(): 返回当前时间的毫秒数
- Date.parse(): 将其他格式的时间字符串转换为该日期的毫秒数,例如
let someDate = new Date(Date.parse("May 23, 2019"));
- 可以使用下列格式
- 月/日/年: 如”5/23/2019”
- 月名 日, 年: 如”May 23, 2019”
- 周几 月名 日 年 时:分:秒:时区,如”Tue May 23 2019 00:00:00 GMT-0700”
- YYYY-MM-DDTHH:mm:ss:sssZ,如”2019-05-23T00:00:00
- Date.UTC(year, month, day, hour, minute, second):传入年、月(0-11)、日(1-31)、时(0-23)、分、秒并转化为毫秒数,如
let y2k = new Date(Date.UTC(2000, 0));
显示
- toLocaleSting(): 输出类似于
2021/5/30 下午3:51:36
- toString(): 输出为
Sun May 30 2021 15:51:36 GMT+0800 (中国标准时间)
- toDateString(): 返回周几、月、日、年
- toTimeString(): 返回时分秒和时区
- toLocaleDateString(): 显示月日年
- toLocaleTimeString(): 显示时分秒
- toUTCString(): 显示完整的UTC时间
还有一些获得单独时间的函数如getYear(),getDate()等可以从函数名得知意思就不再赘述。其中getTime()是获得毫秒的时间
RegExp
RegExp是正则表达式,可以通过一些简单的语法创建。如let expression = /pattern/flags
pattern可以设置lastIndex表示下次从该index处开始
其中pattern是任何正则表达式。每个正则表达式可以带零个或多个标记(flags),用于控制正则表达式的行为,常见的标记有
- g(global): 全局模式,查找所有匹配字符串,而不是匹配一个就结束.
- i(ignoreCase): 不区分大小写
- m(multiline): 多行模式,查找到一行文本末尾会继续查找
- y(sticky): 粘附模式,表示查找从lastIndex开始的字符串
- u(unicode): Unicode模式,启用Unicode匹配
- s(dotAll): dotAll模式,匹配任意字符(如
\n\r
等)
可以使用后面的全称来访问是否设置了这些标记console.log(pattern.global);
console.log(pattern.source);//表达式的字面字符串
console.log(pattern.flags);所有标记
除了使用字面量,还可以使用构造函数来创建。例如:let pattern1 = /[bc]at/i;
let pattern2 = new RegExp("[bc]at", "i");
RegExp的模式参数时字符串,有些时候需要二次转义
let pattern3 = /\[bc\]at/
let pattern4 = new RegExp("\\[bc\\]at", "");
匹配
使用RegExp进行匹配主要是exec(s)方法,方法的参例如:数是待匹配的字符串。如果成功,返回包含第一个匹配的数组,每个字符占一个位置。如果未成功,返回null。返回值虽然是数组,但是额外多加了index和input。index是匹配串中的起始位置,input是待匹配的字符串。
例如:let text = 'mom and dad and baby';
let pattern = /mom( and dad( and baby)?)?/gi;
let matches = pattern.exec(text);
console.log(matches[0]);//mom and data and baby
console.log(matches[1]);// and data and baby
console.log(matches[2]);/ and baby
每个括号表示一个捕获组,也就是第一个会匹配mom and dad and baby,第二个会匹配 and dad and baby.有关捕获组可看这
如果使用了全局标记,那么一次匹配会显示一个匹配的信息,如果没有设置,那么只会返回第一个匹配信息。let text = 'cat, bat, sat, fat';
let pattern = /.at/g;
let matches = pattern.exec(text);
console.log(matches[0]);//cat
matches = pattern.exec(text);
console.log(matches[0]);//bat
如果使用了y,那么下次就会从lastIndex开始进行搜索,并且该标记会覆盖全局标记。注意y和g并不相同let pattern = /.at/y;
let matches = pattern.exec(text);
console.log(matches[0]);//cat
console.log(pattern.lastIndex);//3
let matches = pattern.exec(text);
console.log(matches[0])//null
//和上面不同的原因是这里从3开始搜索,而3占据着.的位置,后面两个字符不是at,所以最终出错
pattern.lastIndex = 5;
matches = pattern.exec(text);
console.log(matches[0]);//bat
test(),如果有模式匹配则返回true
此外RegExp本身还有一些属性
- input: 最后搜索的字符串
- lastMatch: 最后匹配的文本
- lastParen: 最后匹配的捕获组
- leftContext: input字符串中出现在lastMatch前面的文本
- rightContext: 出现在后面的文本
let text = 'this has been a short summer'; |
Boolean、Number、String
这些都是原始值包装类型,也就是对原始值的行为进行扩充。每当用到某个原始值的方法和属性时,后台都会创建一个包含原始值的对象。let s1 = 'some text';//原始值
let s2 = s1.substring(2);//创建了一个包装对象并调用substring函数
包装类型的形成大致过程为:
- 发现调用原始值的函数时,创建包装类型
- 调用实例上的方法
- 销毁实例
这种方式也就意味着我们不能再包装类型上添加方法,因为它使用后会立刻销毁。可以显式的使用Boolean、Number、String创建包装对象,就可以对这些对象进行操作。但是不推荐直接使用包装类型,因为可能会导致一些错误。
构造函数创建的包装类型使用typedef会返回object,因此Object构造方法会根据传入参数不同自动转型。并且如果使用转型函数那么typeof会显示对应类型let obj = new Object('some text');
console.log(obj instanceof String);//true
let s = new String('a');
console.log(typeof s);//object
let value = '23';
let number = Number(value);//转型函数
console.log(typeof number);//number
Number
- toFixed(precision): 设置保留几位小数。例如
let num = 10;
console.log(num.toFixed(2));//10.00 - toExponential(precision): 返回科学记数法形式的字符串,也可以设置精度
- toPrecision(): 他会根据情况返回结果,可能是固定长度,也可能是科学记数法
let num = 99;
console.log(num.toPrecision(1));//1e+2
console.log(num.toPrecision(2));//99
console.log(num.toPrecision(3));//99.0 - isInteger(): 判断一个数值是否是整数,并不是说加了小数点就是整数,例如1.00是整数。他根据小数点之后是否还有位不是0判断是否是整数
String
js使用了两种unicode编码,都是两个字节表示一个字符。
两个字节最多表示65536中字符。但是为了表示更多字符,有时候会使用前16位中某些为特殊字符,然后后16位和前16位共同表示一个字符,这时使用charAt就会出现问题。
例如:let message = String.fromCodePoint(97, 98, 128522, 100, 101);//将数字转换成unicode字符,分别是a, b, 笑脸, d, e
//128522的十六进制是0x1f60a
console.log(message.length);//6(实际上显示时只有五个字符
console.log(message.charAt(1));//b
console.log(message.charAt(2));//<?>
console.log(message.charAt(3));//<?>
console.log(message.charAt(4));//d
console.log(message.charCodeAt(1));//98,b的序号
console.log(message.charCodeAt(2));//55357
- length
- charAt(index): 返回下标处的字符
- charCodeAt(index): 返回下标处的字符对应数值,例如0是48。但是它不会考虑扩展字符
- codePointAt(index): 返回下表处的字符对应数值,考虑了扩展字符
- fromCharCode(…): 根据字符对应数值返回字符串,如
String.fromChatCode(48, 49)//01
- fromCodePoint(…): …
- normalize(): 某些字符可以有多种编码方式,normalize()统一这些编码,共有NFD、NFC、NFKD、NFKC四种规范形式
console.log(String.fromCharCode(0x00c5));//大写拉丁字母
console.log(String.fromCharCode(0x212B));//长度单位埃
console.log(String.fromCharCode(0x0041, 0x030a));//大写拉丁字母上面加个圆圈
这三个虽然编码不相同,但是实际上最后返回的是同一个东西,而使用==是比较不出的,这时我们就需要normalize()规范编码
let a1 = String.fromCharCode(0x00c5));
let a2 = String.fromCharCode(0x212b));
console.log(a1 == a2);//false
console.log(a1.normalize('NFD') == a2.normalize('NFD'));//true
下面是字符串操作方法
- concat(): 将若干个字符串拼接到当前字符串后面,concat()可以接受任意数量的字符串,例如
let s = 'hello ';
let result = s.concat('world');
console.log(result);//hello world - slice,substring, substr: 三个都是获得子字符串,第一个参数都是子字符串开始位置,前两个的第二个参数是结尾位置,而substr第二个参数是抽取字符数量。
- indexOf(),lastIndexOf(): 查找子字符串在字符串中的位置,不同的是indexOf从开始查找,而lastIndexOf从结尾开始查找。第一个参数是要查找的字符串,第二个参数时起始位置
- startsWith、endsWith/includes: 检查一个字符串是否包含另一个字符串,startsWith是从第一个字符开始匹配(检查是否是以这个字符串开头),endsWith是从string.length-substring.length开始匹配。而includes检索整个字符串
let message = 'foobarbaz';
console.log(message.startsWith('foo'));//true
console.log(message.startsWith('bar'));//false,不是以bar开头
console.log(message.endsWith('baz'));//true
console.log(message.includes('baz'));/true - trim(): 删除两边所有的空格
- repeat(times): 把原字符串复制times次
- padStart()、padEnd(): 复制字符串,如果小于指定长度则会填充字符。第一个参数时长度,第二个参数时填充字符
- toLowerCase(), toUpperCase()
下面是匹配(正则表达式):
- match(regexp): 作用和RegExp中的exec类似,只是这里的参数变成了模式串,并且这里全局模式直接返回一个数组
- search(regexp): 返回第一个匹配
replace(regexp, replace_str): 如果第一个参数是一个字符串,那么只会替换第一个匹配到的,如果想要匹配所有,必须使用正则表达式并且加上g。
其中replace_str有几种特殊的符号可以使用| 字符 | 替换文本 |
|-|-|
| $$$$ |$
|
|$'
| 替换匹配子字符串之前的字符串 |
| $` | 匹配子字符串之后的字符串 |
|$n
| 匹配第n个捕获组,关于捕获组可以看前面.范围是0-9 |
|$nn
| 匹配第nn个捕获组,如01-99 |例如:
let text = 'cat, bat, sat, fat';
result = text.replace(/(.at)/g, 'word ($1)');
console.log(result); //word (cat), word (bat), word (sat), word (fat)
字符串有迭代器,可以使用for-of访问每个字符,例如:let message = 'abc';
let stringIterator = message[Symbol.iterator]();
console.'a', done: false] (stringIterator.next());//[value:
for(const c of 'abcde')
{
console. (c);
}
并且我们还可以使用解构操作符把字符串变成数组
let message = 'abcde';
console.message]);//['a', 'b', 'c', 'd', 'e']; ([...
Global
内置对象就是在程序执行前就开始执行的对象,和宿主环境无关,例如Object、Array和String都是内置对象。
window对象已经实现了Global对象的代理,它有Global的一系列方法。
方法:
- encodeURI(),encodeURIComponent(): 用于编码URI来传给浏览器。他会对某些不能出现在URI中的字符进行处理,如空格.其中encodeURIComponent()会对冒号、斜杠、问号等字符也进行编码
let uri = 'http://www.wrox.com/illegal value.js';
console.log(encodeURI(uri));
//http://www.wrox.com/illegal%20value.js',把空格变成%20
console.log(encodeURIComponent(uri));
//http%3a%2f%2fwww.wrox.com%2fillegal%20value.js'; - eval(): 调用eval时,字符串会被解析为语句并执行,例如
eval("console.log('hi')");//hi
Math
math提供了许多数学计算的方法。并且math上提供的计算比普通计算要快很多,因为它的实现更加高效。
math属性
math中的属性包含了一些特殊值
- E: 2.71828
- LN10: 以10为底的自然对数
- LN2: 以2为底的自然对数
- LOG2E: 以2为底e的对数
- LOG10E: 以10为底e的对数
- PI
- SQRT1_2: 1/2的平方根
- SQRT2: 2的平方根
方法:
- min(), max()
- ceil(): 向上舍入
- floor(): 向下舍入
- round(): 四舍五入
- fround(): 返回浮点数表示
- random(): 返回0-1的随机数,其中包含0但不包含1
- 等等
集合引用类型
Array
创建数组let colors = new Array();
let colors = new Array(3);//创建长度为3的数组
let names = new Array("Greg");//只包含一个元素的数组
let colors = ['red', 'blue', 'green']//使用数组字面量创建数组
let colors = [,,,,,];//创建包含5个元素的数组
- from(data, func, this): 从data转换为数组,data可以是集合,map等。func是进行的一些操作。this是func中的this值,但是func不能是箭头函数
- of(): 将一组参数转换成数组
const a1 = [1, 2, 3, 4] |
索引
数组索引和c++最大的不同是它可以动态变化,例如let colors = ['red', 'blue', green'];
colors[3] = 'yellow';//添加一个元素
Array中有一个属性length代表了数组的长度,这个值是可以进行设置的,从而改变数组长度(如果缩减长度会导致原有内容消失)
let colors = ['red', 'blue', 'green'] |
方法
- keys(),values(), entries(): keys是索引的迭代器,values是值的迭代器,entries()是键值对的迭代器,例如
const key = Array.from(a.keys())
console.key)//0, 1, 2, 3 (
const value = Array.from(a.values())
console.'foo', 'bar', 'baz', 'qux' (value)//
const entries = Array.from(a.entries())
console.'foo'], [1, 'bar'], [2, 'baz'], [3, 'qux'] (entires)//[0,
for(const [idx, element] of a.entires())
{
console. (idx);
console. (element);
} - fill(sum, begin, end): 从begin到end填充sum
- copyWithin(index, begin, end): 复制数组begin到end的内容并且插入到以index开始的位置中
- toString(): 每个值都会调用toString()方法
- push(): 拖入任意数量的值并且放入末尾
- pop(): 删除最后一项
- shift(): 取得第一项
- unshift(): 从第一个位置插入
- sort(func): 排序,可以按照指定的func进行排序
- reverse(): 反向排序
- concat(): 拼接
- indexOf(), includes(), lastIndexOf(): 搜索某一个元素在数组中的位置,indexOf(), includes()从前往后搜索,lastIndexOf()从后往前.indexOf()和lastIndexOf()没有搜索到返回-1.includes()没有搜索到返回false。他们进行比较时使用====,也就是两项必须严格相等
- every(func): 对每一项都运行函数,如果全部返回为真,则结果为真
- filter(func): 运行函数为true的项会组成数组返回
- foreach(func): 对每一项都运行函数
- map(func): 对每一项都运行函数,返回由函数结果构成的数组
- some(func): 只要有一项返回为true结果就为true
let number = [1, 2, 3, 4, 4]
let result = number.every((item, index, array)=>item > 2);//false
let mapres = number.map((item, index, array)=>item * 2);
number.forEach((item, index, array)=> ); - reduce(func): 对数组中数据进行归约
let values = [1, 4, 9, 16]
let sum = values.reduce((prev, cur, index, array)=> prev + cur);//30
第一次执行时prev=1,cur=4,第二次执行prev=5(前面的归约结果), cur=9(第三项Map
创建:const m = new Map();
const m1 = new Map([
['key1', 'val1'],
['key2', 'val2'],
['key3', 'val3']
]);
map和object类型都可以插入键值对,但是他们还是有很大区别的。Object类型的键只能是数值,字符串或符号,而map可以是任意类型。其次map内部是有序的(插入顺序),而Object是无序的。我们可以使用entries()获得一个个按照插入顺序排列的(key, value)形式的数组
for(let pair of m.entries()) |
函数:
- set(): 添加键值对
- get()/has(): 输入键,查询值
- delete()/clear(): 删除
const m = new Map();
m.get("firstName");
m.set("firstName", "Matt");
m.has("firstName");//true
m.delete("firstName"); - keys()/values(): 返回key或value的迭代器
键和值在迭代器遍历时是可以修改的,但是在Map内部不会修改。当然,这种修改不会影响使用这个键访问值const m = new Map({% post_link "key1", "val1" %});
for(le tkey of m.keys())
{
key = "newKey";
alert(m.get("key1")//val1,说明在map内没有被修改
}
const keyObj = {id: 1};
const m1 = new Map({% post_link keyObj, "val1" %});
for(let key of m.keys())
{
key.id = "newKey";
alert(m.get(key);//val1
}
WeakMap
弱映射表示映射的键是弱的,一旦键的引用被清除,这个键值对就会被清除。
他和普通的Map不同在于普通的map的键是在对象中独立存在的,除非调用delete否则不会被清除,而WeakMap中键直接引用外部变量,外部变量被清除这个键值对也就被清除。
const w = new WeakMap(); |
由于container对象保有对key的引用,所以这个键值对暂时不会被清除,一旦调用remove_reference清除了外部引用之后,这个键值对将自动清除。
因为引用被删除就会自动回收,所以它可以很方便的给某些数据添加额外属性,省的每次都要deleteconst w = new WeakMap();
const loginButton = document.querySelector('#login');
w.set(loginButton, {disabled: true});
set
set的基本函数和map类似,并且它的插入也是按序的。但是js里面的set和其他的set不同。它并没有提供集合操作方法,需要我们自己实现。
static union(a, ...bSets) |
此外,他也有WeakSet,效果和WeakMap相同