05-标准库
第五章 标准库¶
统计信息:字数 23101 阅读47分钟
2021-11-17 2023-04-06
5.1 Object 对象¶
工具函数¶
Object() 本身就是一个函数,可以把传入的值转化成一个对象,如果传入的是null或者undefined,得到的就是一个空对象。如果传入的参数是原始类型的值,那么产生的对象是其包装对象的实例。如果传入的是一个对象,那么返回的还是原始对象。可以利用Object()这个函数判断一个变量是否是对象。
let obj = Object(1);
obj instanceof Number // true
obj instanceof Object // true
构造函数¶
使用 new Object() 创建一个新对象(通常用对象字面量创建对象)
静态方法¶
静态方法和实例方法:Object 对象上的方法是静态方法,Object 原型链上的方法就是实例方法(Object.prototype.function)。实例方法将被所有的实例对象所共享。
主要是下面两个静态方法
Object.keys(obj) // 返回对象的属性(不包含不可枚举属性,返回一个属性数组,不包括对象继承的属性)
Object.getOwnPropertyNames(obj) // 返回对象的全部属性数组(包含不可枚举属性,length)
其他静态方法了解
对象属性模型的相关方法
Object.getOwnPropertyDescriptor():获取某个属性的描述对象。
Object.defineProperty():通过描述对象,定义某个属性。
Object.defineProperties():通过描述对象,定义多个属性。
控制对象状态的方法
Object.preventExtensions():防止对象扩展。
Object.isExtensible():判断对象是否可扩展。
Object.seal():禁止对象配置。
Object.isSealed():判断一个对象是否可配置。
Object.freeze():冻结一个对象。
Object.isFrozen():判断一个对象是否被冻结。
原型链相关方法: 该方法可以指定原型对象和属性,返回一个新的对象
Object.create()
Object.getPrototypeOf() // 获取对象的Prototype对象
实例方法¶
Object实例对象的方法,主要有以下六个
Object.prototype.valueOf();
// 返回当前对象对应的值(对象本身,很少使用)
Object.prototype.toString()
// 返回当前对象对应的字符串形式(很少使用)
Object.prototype.toLocaleString()
// 返回当前对象对应的本地字符串形式(判断对象的具体类型 [Object Array])
Object.prototype.hasOwnProperty()
// 判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性(判断一个属性是否存在于对象上)
Object.prototype.isPrototypeOf()
// 判断当前对象是否为另一个对象的原型(不用)
Object.prototype.propertyIsEnumerable()
// 判断某个属性是否可枚举(不用)
5.2 属性描述对象¶
简单说:描述对象的属性的特点(对象的属性是否只读,可查询,可更改,可遍历等)
value: 123,
writable: true,
enumberable: true,
configurable: false,
get: undefined,
set: undefined
- value 属性的值
- writable 属性可否改变
- Enumberable 属性是否可遍历(if false, for-in and Object.keys will skip this propertity)
- configurable 属性可配置(是否可以删除)
- get 取值函数
- set 设置函数
利用上面的属性,可以直接设置一个对象的属性是只读属性;这部分属性项目中很少用到。
5.3 Array 对象¶
构造函数¶
let arr = new Array(5); // 会创建一个长度是5的空数组
console.log(arr[0]); // undefined 每一项都是空的
let arr2 = new Array(1, 2);
// 会创建一个数组 [1, 2];
使用构造函数创建数组:
-
如果传入一个数值,那么数值就是数组的长度(如果数值是小数就会报错),每一项都是空的
-
如果传入多个参数,就构成数组的新的项
-
如果传入一个数组,那么就返回和原始值相同的数组
所以,使用数组字面量创建新数组是很好的办法。
静态方法¶
由于 typeof array === 'Object', 所以使用 Array.isArray(arr) => true 即可精确判断数组,这个是 ES6 的语法。
实例方法¶
常用 push pop shift unshift reverse slice splice
join(seperator) 把数组用分隔符链接并转化成字符串。如果某一项是 undifined or null, 对应的字符串就是空字符串。如果没有分隔符,默认使用逗号作为分隔符。通过 call 方法,可以把数组的join使用在字符串或者对象上,可以添加字符串的分隔符,或者对象值的分隔符。
Array.prototype.join.call('hello', '&');
// h&e&l&l&o
let obj = {name: "Mike", age: '20'}
Array.prototype.join.call(obj, '-');
// 'Mike-20'
concat 将多个数组连接成新的数组,返回值是新数组,不改变原始值。如果传入参数是多个数值,就把数值加入到数组的后面;如果传入的是引用对象,那么就浅拷贝对象的值。
sort 排序,默认按照字符字典的位置进行排序,原数组将会被改变;如果希望按照自定义的方式排序,就在后面加入一个自定义的函数(可以比较一下冒泡排序法快速排序法和这里的排序法的复杂度)。如果是一个数组中是对象,然后对于对象中的某个属性进行排序,这种方式排序比上面两个方案更好。
array.sort(function(a, b) {
return a - b;
});
map 将函数中的每一项执行某个函数,返回值是执行函数后的新数组。如果某一项是空,那么会跳过整个位置;如果某一项是undefined就会执行这个函数。这个函数很好使用,可以把一个函数进行转换操作。
array.map(function(item, index, array) => {
return sth;
});
forEach 会对函数的每一项执行函数,没有返回值。如果仅仅想对于函数的每一项执行一个操作,不需要获取新的数组,就使用这个函数。map函数使用较多。同理,forEach 函数会跳过空位,不会跳过 undefined。
filter 函数:将函数的每一项进行过滤,如果是真实就返回,返回值是满足过滤条件的新数组。
let newArr = array.filter(function(item, index, array) {
return (item > 10);
});
some 判断数组的每一项,如果有一项满足条件,那么返回真,如果全不满足条件返回假。如果是空数组,就返回假。
every 判断数组的全部,如果全部满足条件就返回真,否则返回假。如果传入参数是空数组,就返回真(注意这个情况!!!)
reduce 和 reduceRight 从左向右或者从右向左依次处理数组的每一项,将每一项相乘或者相加。
array.reduce(function(a, b){
return a + b
}, 10);
// 第二个参数是初始值,从10开始加;
// 如果是空数组,第二个参数很重要,避免出错 Reduce of empty array with no initial value
如果是加法或者乘法,这两个方法相同,如果是减法或者除法,就会得到不同的值。当然可以使用这个方法,找出数组的最大值最小值,或者找到字符串最长的值。
indexOf lastIndexOf 可以判断某个字符串出现的位置,但是不能判断NaN(因为 NaN !== NaN)。
不常用
toString 将数组转化成字符串输出
valueOf 返回数组本身
链式使用¶
如果一个方法的返回值是一个数组,可以继续进行操作。
var users = [
{name: 'tom', email: 'tom@example.com'},
{name: 'peter', email: 'peter@example.com'}
];
users
.map(function (user) {
return user.email;
})
.filter(function (email) {
return /^t/.test(email);
})
.forEach(function (email) {
console.log(email);
});
5.4 包装对象¶
实际项目中很少使用 https://wangdoc.com/javascript/stdlib/wrapper.html
包装对象:字符串、布尔值、数值对应的对象就是包装对象。目的:JS是基于对象的,所以这些数据类型可以表现成对象模式。
如果把 Number Boolean String 作为普通函数,可以把一个参数转化成简单对象,如果作为构造函数 new Number(parameter) 就会转化成包装对象,包装对象和原始的数值不全等。
let num1 = new Number(1);
// num1 !== 1 构造函数,num1是包装对象
let num2 = Number('2');
// 简单函数,num2 是数值
静态方法¶
valueOf 获取包装对象的原始简单类型值
toString 将包装对象转换成为字符串
自动转换¶
包装对象和原始简单类型的自动转换:一个字符串具有 length 的属性,实际上字符串不具有这个属性(对象才具有属性),JS内部会首先将字符串转化成包装对象,然后获取对象的长度,返回对象的长度后,将这个包装对象转换成原始的数值。 如果给一个字符串手动添加属性,那么会转化成包装对象,这时候不报错。如果使用点语法获取字符串的某个属性,包装对象已经自动转换成简单类型,这个属性的值就是 undefined.
自定义方法¶
给构造函数的原型链加上自定义方法,那么包装对象可以直接调用这些方法
String.prototype.double = function() {
return this.valueOf() + this.valueOf();
}
// String 包装对象具有自定义的double方法
'abc'.double();
// 字符串转换成包装对象,然后去原型链上查找这个double方法,并执行
下面介绍三个包装对象
5.5 Boolean 包装对象¶
Boolean 作为普通函数,可以将一个参数转换成布尔值,只有五个可以转换成 false 的情况,undefined, null, false, 0, NaN。其他的都是true,例如'false', [], {}, /foo/, function(){} 都是 true。作为简单函数,Boolean 等于!! 运算符,通常使用 !! 转换成布尔值。
Boolean 作为构造函数,可以将一个参数转换成布尔值包装对象 new Boolean(),使用 valueOf() 可以获取原始的值。对于 false 和 null ,使用构造函数转换成对象后,他们的值是 true。这两个特例在普通函数和构造函数获得的结果是不同的。
所以,通常作为普通函数使用(直接使用 !! 进行转换)。
5.6 Number 包装对象¶
Number 对象可以当做普通函数(工具函数)或者构造函数使用。
Number 包装对象具有很多实例方法:toString, toFixed .toExponential ,toPrecision把数值对象转换成一个字符串的整数、小数、科学计数法、精度数据。主要作用就是,如果后端给了一个值,在前端界面需要显示几位小数,或者显示科学计数法,首先转换成对应的字符串,然后在界面上渲染这个值。
同理,Number 对象的原型上可以绑定自定义方法。
5.7 String 包装对象¶
构造函数 包装对象¶
let strObj = new String();
使用构造函数可以创建包装对象,转换后的包装对象具有类似数组的属性:可以直接通过下标获取对应位置的字符,可以length获取对应的长度。具有valueOf的方法,可以转换成原始的值。
工具函数=>普通字符串,可以直接转换成字符串
静态方法¶
fromCharCode 可以将字符串代码转换成字符串 String.fromCharCode(104, 101, 108, 108, 111)
很少使用
实例方法¶
- length 返回字符串的长度:如果某个位置是空字符,那么也计算长度。“abc ”的长度是6;
- charAt charCodeAt 返回字符串某个位置的字符或者字符码(直接可以通过下标属性获取)
- concat 连接字符串,不会改变原始字符串,如果参数不是字符串,首先把每个参数转换成字符串,然后再拼接。如果全部参数是字符串,不需要转换,直接使用加号即可。如果参数是数值布尔值和字符串混合,使用concat拼接字符串更好。
- slice 切去一段字符串,使用很多,规范类似数组。substring方法类似slice,但是有问题,所以优先使用slice。
- substr 切去一段字符串。第一个参数是位置,第二个参数是切的长度(和slice不同)。如果两个都是位置(str.indexOf),使用slice更好,如果确定切去的长度,那么使用substr更好。
- indexOf()/ lastIndexOf() 获取字符出现的位置
- trim 删除字符串末尾的空格 不改变原始字符串,末尾的回车换行制表符都可以删除(\n \r \t \v)
- toLowerCase-toUpperCase 转换成大写或者小写
- match('at') 原字符串是否匹配某个子字符串,返回一个数组,存放成功匹配的第一个字符串,如果没有找到返回的是null。传入的参数可以使正则表达式。返回的数组具有index input 属性,可以获取匹配的原始字符串和开始的位置。
- search('abc') 作用类似于 match 返回值是匹配第一个字符串的位置,如果不匹配返回值是-1
- replace('abc', 'cba') 替换字符串,如果第一个参数不是正则表达式的全局匹配,只替换第一个出现的字符串。
- split(seperator, how many) 使用分隔符将字符串分割成数组。如果传入的分隔符是空字符串,那么就把每一个字符分割。如果不传入分隔符,返回值就是字符串数组(只有一项);传入的第二个可选参数是返回值数组的最大长度。可以传入正则表达式作为分隔符。
- localeCompare 比较两个字符串(使用字符串字典的位置)大写小于小写,返回值是数字,如果两个字符串相等返回0。利用这个方法,可以对字符串进行排序输出。默认按照英文比较,第二个参数可以传入其他语言比较。
5.8 Math 对象¶
Math 对象不是构造函数,静态属性、静态方法必须在原生对象上使用,提供常用的数学方法
静态属性¶
获取数学常量
Math.PI
Math.E
Math.SQRT2
Math.LN2
静态方法¶
ceil floor 取整函数
pow 指数 log 对数
sqrt 平方根 round 四舍五入
random 随机值
所有三角函数(参数是弧度)
获取最值时,传入的参数是若干个数值。如果传入数值数组,返回值是NaN。
random产生的随机值是[0, 1);
例子
返回一个任意范围内的随机数
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
返回随机字符串
function random_str(length) {
var ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
ALPHABET += 'abcdefghijklmnopqrstuvwxyz';
ALPHABET += '0123456789-_';
var str = '';
for (var i = 0; i < length; ++i) {
var rand = Math.floor(Math.random() * ALPHABET.length);
str += ALPHABET.substring(rand, rand + 1);
}
return str;
}
random_str(6) // "NdQKOr"
5.9 Date 对象¶
国际标准时间(UTC) 1970-01-01作为时间的零点
工具函数¶
工具函数 Date() 返回当前时间的字符串,如果传参,仍然返回当前时间的字符串。
'Mon Jul 08 2019 11:47:21 GMT+0800 (中国标准时间)'
构造函数¶
可以把参数转换成时间处理;如果不传参,获取的实例就是当前的时间
let today = new Date();
参数类型很多,都可以转换成时间对象,只要是能被Date.parse()
方法解析的字符串,都可以当作参数。如果参数是负数,表示1970年前的时间。
// 参数为时间零点开始计算的毫秒数
new Date(1378218728000)
// Tue Sep 03 2013 22:32:08 GMT+0800 (CST)
// 参数为日期字符串
new Date('January 6, 2013');
// Sun Jan 06 2013 00:00:00 GMT+0800 (CST)
// 参数为多个整数,
// 代表年、月、日、小时、分钟、秒、毫秒
new Date(2013, 0, 1, 0, 0, 0, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
参数的具体规则很复杂,详情参考 https://wangdoc.com/javascript/stdlib/date.html 如果涉及时区需要转换。还有很多第三方库去处理时间。[www.datejs.com] 日期字符串,毫秒数等都可以转换。
如果两个日期对象减运算,首先转化成数值(毫秒),返回的就是日期的差值(毫秒数);如果两个时间相加,首先转化成字符串,结果就是两个字符串的拼接(不是加在一起的毫秒数)
静态方法¶
Date.now() 现在距离1970年的毫秒数,是当地时区的时间
Date.parse() 将字符串转换成毫秒数,如果字符串不合适,返回NaN;下面是符合的字符串
Date.parse('Aug 9, 1995')
Date.parse('January 26, 2011 13:51:50')
Date.parse('Mon, 25 Dec 1995 13:30:00 GMT')
Date.parse('Mon, 25 Dec 1995 13:30:00 +0430')
Date.parse('2011-10-10')
Date.parse('2011-10-10T14:48:00')
Date.UTC() 转换成世界标准时间的毫秒数
实例方法¶
实例方法分为 to get set 等,可以直接获取或者设置时间(字符串、JSON、标准时间、当地时间、年月日时分秒、毫秒等)使用方法参见上面的链接。
5.10 RegExp 正则对象¶
创建正则表达式¶
创建正则表达式有两种方法,构造函数和对象字面量;对象字面量就是两个斜杠;使用字面量创建正则对象更多见,方便增加修饰符。第二个案例中声明正则对象是等价的。
let arr = [];
let obj = {};
let reg = /xyz/; // 如果是空的就表示注释,会报语法错误
let reg2 = new RegExp('xyz');
let reg = /xyz/g;
let reg = new RegExp('xyz', 'g');
https://wangdoc.com/javascript/stdlib/regexp.html
实例属性¶
判断正则对象具有哪些修饰符 flags,这是只读属性。正则表达式的属性不常用。
let reg = /abc/igm;
console.log(reg.flags);
实例方法¶
test 查看字符串是否匹配,返回布尔值;如果正则对象是空,那么所有字符串返回真。方法的返回值是undefined
console.log(/abc/.test('abcdef')); // true
exec 查看字符串是否匹配,返回值是匹配的字符串构成的数组。如果没有匹配到,返回的是null。默认正则返回的数组长度就是1,内容和原始正则内容相同。如果正则包含括号,返回的是可能的多个组合。
let reg = /a(b+)a/;
let arr = reg.exec('_abbba_aba_');
arr // ['abbba', 'bbb']
正则和字符串结合¶
match search replace split
match 返回匹配的字符串数组(失败返回null)
search 返回匹配字符串的位置(失败返回-1)
replace 按照第一个参数匹配字符串,然后替换成第二个字符串。通常修饰符是g用来替换全部的字符串。replace 的第二个参数复杂用法 https://wangdoc.com/javascript/stdlib/regexp.html
'aaa'.replace(/a/g, 'b'); // 'bbb'
' testabg '.replace(/^\s+|\s+$/, ''); // 去掉字符串首尾的空格
split 使用正则作为分隔符(可以使用多种分隔符)
let str = 'a ,b, c, d';
let arr1 = str.split(',');
let arr2 = str.split(/, */); // 这样可以去除多余的空格
常用的是 replace 和 split 方法
复杂的匹配规则¶
https://wangdoc.com/javascript/stdlib/regexp.html
5.10.1 字面量字符和元字符¶
-
字面量字符:单独一个字符串
/dog/.text('small dog')
-
点字符(.)匹配除去回车换行的任何一个字符
/d.g/
可以匹配'dig'
不能匹配'drag'
-
或字符(|)表示或,
/cat|dog/
表示满足任何一个条件即可 -
开始符号(^)必须以这个字符开始;
-
结束符号($) 必须以这个字符结束
选择、开始、结束通常同时使用,使用很多 /^test$/.test('test 123 test')
return false;
5.10.2 转义符¶
正则表达式中的特殊符号需要经过转义,在符号前加上反斜杠即可 /1\+1/.test('1+1')
需要转义的符号一共12个。
如果使用正则对象字面量创建正则对象,一个转义符号;
如果使用构造函数创建正则对象,需要加入两个转义符号(因为字符串内部反斜杠也是转义字符,两个反斜杠先转义成一个反斜杠,然后被正则表达式再转义一次,所以避免使用构造函数创建正则表达式对象)
5.10.3 特殊符¶
回车换行分页等文本操作符号 null
\cX
表示Ctrl-[X]
,其中的X
是A-Z之中任一个英文字母,用来匹配控制字符。[\b]
匹配退格键(U+0008),不要与\b
混淆。\n
匹配换行键。\r
匹配回车键。\t
匹配制表符 tab(U+0009)。\v
匹配垂直制表符(U+000B)。\f
匹配换页符(U+000C)。\0
匹配null
字符(U+0000)。\xhh
匹配一个以两位十六进制数(\x00
-\xFF
)表示的字符。\uhhhh
匹配一个以四位十六进制数(\u0000
-\uFFFF
)表示的 Unicode 字符。
5.10.4 字符类¶
表示可以有一系列字符可以匹配,满足一个字符即可(或字符可以匹配多个单词,字符类可以匹配多个字符)
/[abc]/.test('orange') => false
同时 /[abc]/.test('banana') => true
- 脱字符
/[^abc]/.test('nanana') => true
只有字符串中具有abc 外的其他字符就返回true - 连字符
/[a-fA-F]/
可以省略连续的字符数字等(注意,大写和小写中间有其他字符,不能/[a-Z]/
)
5.10.5 预定义模式¶
\d\w\s
分别匹配数字、字母数字下划线、空格(换行)如果是大写就是相反的匹配
5.10.6 重复类量词符¶
{n, m} 表示一个字符出现的次数,如果传单个参数表示确定的次数,如果m是空表示没有最大值。
? * + 是上面的重复类的简写
?等价于 {0, 1}
*等价于 {0, }
+等价于 {1, }
5.10.7 修饰符¶
g 全局匹配
i 忽略大小写匹配
m 忽略换行符(^$)前后有换行符可以匹配
此外,还有贪婪模式、组匹配(括号表示分组匹配,括号的嵌套、非捕获组、先行断言)需要的时候加强
5.11 JSON 对象¶
JSON 格式:规范严格,主要用于数据传输,取代 XML。
JSON 对象:JS 中的原生对象,具有下面两个方法 JSON.parse(), JSON.stringify()
如果节点很多,使用这两个办法很消耗性能:20ms左右。
JSON.stringify()¶
JSON.stringify(para1, para2, para3) 把JSON转换成字符串
通常使用第一个参数:将一个合法的值转化成JSON字符串,这个值可以使简单类型或者引用类型(对象数组)。如果对象的属性是 undefined, 函数或者XML对象,那么就会忽略这个属性;如果数组的成员是上面三种情况,会转化成null。转换过程中会忽略对象的不可遍历属性
第二个参数是可选参数,可以设置转换后字符串的类型,或者批量处理转换对象的键值对。
第三个参数是可选参数,可以设置为数值,表示结果键值之间的空格(用户友好),此时第二个参数传null即可。
JSON.parse()¶
把字符串转换成JSON对象;如果传入的对象不是有效的字符串,那么会报错(例如字符串是单引号)如果不能完全确定输入的字符串是否是合规的,最好做一个错误处理。