标准库(标准API)
- 库:liberary
- API:应用程序编程接口,Application Programing Interface
- 标准:ECMAScript标准
Object
静态成员
- keys(某个对象),得到某个对象的所有属性名数组
- values(某个对象),得到某个对象的所有属性值数组
- entries(某个对象),得到某个对象的所有属性名和属性值的数组
实例成员
实例成员可以被重写
所有对象,都拥有Object的所有实例成员
- toString方法:得到某个对象的字符串格式
默认情况下,该方法返回"[object Object]";
而对于Number对象来说,toString方法是被重写的,实现不太一样。
function MyNumber(n) {
this.toString = function() {
return "" + n;
}
}
- valueOf方法:得到某个对象的值
默认情况下,返回该对象本身
在JS中,当自动的进行类型转换时,如果要对一个对象进行转换,实际上是先调用对象的valueOf方法,然后调用返回结果的toString方法,将得到的结果进行进一步转换。此处需要重新看视频。
下面的代码的输出是什么呢?
var obj = {
x: 13,
y: 34534,
valueOf() {
return 123;
}
}
console.log(obj + 1);
// 如果调用了valueOf已经得到了原始类型,则不再调用toString
上面的代码输出是124,而不是 1231,是因为对象先调用了valueOf,获取的对象已经是基本类型123了,就不会再调用toString方法了
Function
所有函数都具有Function中的实例成员
语法:arguments:在函数中使用,获取该函数调用时,传递的所有参数
arguments是一个类数组(也称为伪数组:没有通过Array构造函数创建的类似于数组结构的对象),伪数组会缺少大量的数组实例方法
arguments数组中的值,会与对应的形参映射 下面举例子讲解形参映射的问题
function test(a,b) {
console.log(arguments);
}
test(23, 5, 6, 2, 233, 5, 6, 7);
1.argumnets可以获取到所有的参数
function test(a, b) {
arguments[0] = "abc";
b = 123;
console.log(a, b);
console.log(arguments);
}
test(1,2);
我们发现两个值都改了,这叫映射。他们两个是一个东西,前提是一开始建立了映射。
再看下面这一种情况:
test();
为什么是上面的没有互相修改呢?是因为没有在一开始通过test建立映射,映射失败了。只有test传了参数,argumnet这个伪数组里面有内容才能和形式参数之间建立映射。这里传递参数包括你传递了undefined等别的参数,完全啥都不写是建立不了映射的。
再看下面这一种情况:
test(1);
这个只有第一个参数和形参a建立了映射,改变a或者形参另外一个都会跟着改变。
再看下面这一种情况:
test(1,undefined);
这个情况,两个参数都建立了映射,改变a,b或者argument都会跟着改变。
下面的代码可以将arguments这个伪数组转化一个真的数组。
function test() {
console.log(arguments);
//将arguments转换为真数组
var newArr = [].slice.call(arguments)
console.log(newArr);
}
test(23, 5, 6, 2, 233, 5, 6, 7);
简单理解可以认为是将数组的slice方法给伪数组用了。其实类似于iOS里面的方法里面的target转发。
实例成员
- length属性,得到函数形参数量
- apply方法:调用函数,同时指定函数中的this指向,参数以数组传递
- call方法:调用函数,同时指定函数中的this指向,参数以列表传递
- bind方法:得到一个新函数,该函数中的this始终指向指定的值。
通常,可以利用apply、call方法,将某个伪数组转换伪真数组。
下面先举一个例子
function sayHello(a, b) {
console.log(this.name, this.age);
console.log(a, b);
}
var user1 = {
name: "asfd",
age: 123
};
var newFunc = sayHello.bind(user1, 1, 2);
//调用
newFunc();
sayHello.call(user1, 1, 2);
sayHello.apply(user1, [1, 2]);
分析一下上面的代码,sayHello如果是直接调用 比方说用下面的代码调用 sayHello(1,2),则这个函数里面的this是指向的是window的,这里我们用 bind(user1,1,2)则这里其实作用是将实际的调用者换成了user1这个对象,而后面的1,2,仍然是sayHello方法需要的参数。
下面我们比较一下三个的差别: 1.bind 和另外两个相比多一个括号,传递的参数直接跟在调用对象的后面 2.apply 和 call都是一个括号,call的参数传递方式和bind一样,而apply是另外用一个中括号去传递参数的。
伪数组转真数组的最常见做法
function test() {
console.log(arguments);
//将arguments转换为真数组
var newArr = [].slice.call(arguments)
console.log(newArr);
}
test(23, 5, 6, 2, 233, 5, 6, 7);
1.arguments 是伪数组,里面并没有slice这个方法。[] 这个是一个空数组,空数组可以调用slice方法 slice 方法的作用是什么?slice(1,3)表示从数组中下标为1的开始取,然后取到下标为2的元素,如果直接写slice()表示整个数组取出来。而slice方法里面有this的指向,这里将this的指向为arguments。这样其实就相当于对arguments进行这个操作,最后得到一个真数组。
2.更改this指向的核心目的其实就是想用一个本身和自己没关系,也不能调的方法。
Array构造器
凡是通过Array构造函数创建的对象,都是数组
创建方法 new Array(length) 创建长度为length的数组。
静态成员
- from方法:可以将一个伪数组转换为真数组,ES6才出现的方法。
- isArray方法:判断一个给定的数据,是否为一个真数组
- of方法:类似于中括号创建数组,依次赋予数组每一项的值
function test(){
console.log(Array.isArray(arguments));
var newArr = Array.from(arguments);
console.log(newArr, Array.isArray(newArr));
}
test(1,4,6,57,89,33)
实例成员
- fill方法:用某个数据填充数组,比方说原数组有5项,现在可以使用fill(1),现在数组里面所有项都是1了。
- pop :删除数组的最后一个元素并返回删除的元素。
- push 向数组的末尾添加一个或更多元素,并返回新的长度
- reverse:将当前数组颠倒顺序
- shift 1.将数组的第一项删除掉,2.方法的返回值,返回第一个元素。
- sort:对数组进行排序,不能直接使用,自带的排序只是按照第一位进行排序的,也就是可能会出现
12小于2的情况,如果需要排序需要传递一个函数
arr.sort(function(a, b) {
return a - b;
});
- splice 选取数组的一部分,并返回一个新数组。
- unshift 向数组的开头添加一个或更多元素,并返回新的长度。
sort的使用
var arr = [3, 211, 32, 11, 5, 4];
arr.sort();
console.log(arr);
上面的排序结果是:
上面的排序结果不是按照我们的想法,是因为上面的是按照编码大小取比较。就是说按照前面字符编码大小从第一位开始比较,如果第一位已经比较出来,就不继续往下比较了。
var arr = [3, 211, 32, 11, 5, 4];
arr.sort(function(a, b) {
return a - b;
});
console.log(arr);
上面的function(a, b) < 0, a排在b前面。 function(a, b) = 0, 位置不变。 function(a, b) > 0, b排在a前面。
纯函数、无副作用函数:不会导致当前对象发生改变
- concat 连接两个或更多的数组,并返回结果
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = [7, 8, 9];
var newArr = arr1.concat(arr2, arr3);
console.log(newArr);
- includes: 数组中是否包含满足条件的元素。 是否包含是使用的严格相等,对于对象,必须是同一对象才行。
var arr = [32, 6, 67, 3, 23, 4];
// 从数组下标3的位置开始寻找,目标是67
console.log(arr.includes(67, 3));
var arr = [{ x: 1, y: 2 }, { x: 3, y: 4 }];
console.log(arr.includes({
x: 1,
y: 2
}));
官方文档中[,] 代表这个参数是可选的,可以传也可以不传。
- join :把数组的所有元素放入一个字符串。 这个方法可以传递参数,指定字符之间是用什么相连在一起的。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var energy = fruits.join();
//var energy = fruits.join("-");
console.log(energy);
-
slice 选取数组的一部分,并返回一个新数组。
-
indexOf 搜索数组中的元素,并返回它所在的位置。某个元素第一次出现的下标。没有找到返回 -1
-
lastIndexOf 搜索数组中的元素,并返回它最后出现的位置。某个元素最后一次出现的下标。没有找到返回 -1
-
forEach: 遍历数组
var arr = [234, 65, 2, 423, 5];
arr.forEach(function(item,index,array){
console.log(item,index,array);
});
forEach内部用的函数可以传递三个参数,item 是当前的迭代的元素,index是下标,array是当前的数组。
- every:是否所有元素都满足条件
- some:是否至少有一个元素满足条件
var arr = [37, 25, 48, 55, 30];
//判断是否所有同学都及格
// var result = arr.every(function(item) {
// return item >= 60;
// });
// console.log(result);
//判断是否至少有一个同学及格
console.log(arr.some(function(item) {
return item >= 60;
}));
传递的函数同样有三个参数,item,index,array,上面只用了item。
- filter:过滤,得到满足条件的元素组成的新数组
var arr = [77, 25, 88, 55, 30];
//得到所有及格的分数
var newArr = arr.filter(function(item) {
return item >= 60;
});
console.log(newArr);
- find: 查找第一个满足条件的元素,返回元素本身,如果没有找到,返回undefined
- findIndex: 查找第一个满足条件的元素,返回元素的下标
var arr = [{
name: "a",
age: 11,
score: 55
}, {
name: "b",
age: 12,
score: 65
}, {
name: "c",
age: 22,
score: 85
}];
//得到及格的学生(找第一个的下标)
var index = arr.findIndex(function(item) {
return item.score >= 60
});
console.log(index);
//得到及格的学生(找第一个)
// var result = arr.find(function(item) {
// return item.score >= 60
// });
// console.log(result);
//得到及格的学生
// var result = arr.filter(function(item) {
// return item.score >= 60
// });
// console.log(result);
- map:映射,将数组的每一项映射称为另外一项
var arr = [55, 66, 22, 33, 44, 88];
//得到一个新数组,新数组的每一项是一个对象
//对象中包含两个属性:name、score
var newArr = arr.map(function(item, i) {
return {
name: "学生" + (i + 1),
score: item
}
});
//得到一个学生的姓名数组
newArr = newArr.map(function(item) {
return item.name;
});
console.log(newArr);
- reduce:统计,累计
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素。 reduce 一共可以传递两个参数,第一个是callback 回调函数,一个是initialValue,初始值,给回调函数用的。 initialValue 可以传也可以不传,不传的时候当数组中没有一个元素时候执行reduceh会报错,当只有一个的时候,回调函数不会被执行。
回调函数接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。
callback (执行数组中每个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue),函数必须的参数)
2、currentValue (数组中当前被处理的元素,函数必须的参数)
3、index (当前元素在数组中的索引,非必须的参数)
4、array (调用 reduce 的数组,非必须的参数)
initialValue (作为第一次调用 callback 的第一个参数。)
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
})
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
},0)
这里0可以填,可以不填。
上面还可以简写为
var sum = arr.reduce((a,b)=> a+b,0);
console.log(arr, sum);
特别需要注意的点:
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = [7, 8, 9];
var newArr = arr1.concat(arr2, arr3);
console.log(newArr);
var arr = [1, 2];
var sum = arr.reduce(function(s, item) {
console.log("回调", s, item);
return s + item;
}, 0);
console.log(sum);
// 链式编程:每一个函数调用返回的类型一致
var arr = [22, 33, 44, 55, 66, 77, 88];
// 先对数组进行随机排序
// 只取及格的分数
// 得到学生对象的数组(每个学生对象包含姓名和分数)
var result = arr.sort(function() {
return Math.random() - 0.5;
}).filter(function(item) {
return item >= 60;
}).map(function(item, i) {
return {
name: `学生${i+1}`,
score: item
}
});
console.log(result);
1.concat一次可以把多个数组合到一个数组中 2.includes除了可以查找基本元素,还可以查找对象.还可以设定可以从某个位置开始查找。 3.forEach循环的时候可以设定在循环的调用某个函数 4.every 和some 判断里面的元素是否满足某个条件 5.filter 过滤,筛选。可以写一个函数,通过函数去判断元素是否满足条件,最后把满足条件的元素放到一个数组中。 6.findIndex 和filter类似,也可以从对象中筛选。 7.Map可以将这样一个数组映射成另外一个数组。
array 的slice 和splice方法使用
slice 单词的意思是切片(不破坏原物),slice 可以参数可以不传参数,代表从开头开始截取,截取到末尾。可以传一个参数,如果参数如正数,代表从开头开始数。如果是负数,则从末尾开始数。一个数代表从当前位置到末尾。如果是传递两个参数,代表从当前位置开始数,到结束的位置,不包含结束的位置。
splice 是拼接(修改原物)这个方法可以传递两个,三个或者三个以上。传递两个参数代表的是从哪个位置开始删除元素,删除几个元素。从第三个开始表示从当前的位置插入多少个元素。
const fruits = ['apple', 'banana', 'orange', 'grape', 'kiwi']
// 从索引1开始到索引3(不包含)
const result1 = fruits.slice(1, 3)
console.log(result1) // ['banana', 'orange']
console.log(fruits) // ['apple', 'banana', 'orange', 'grape', 'kiwi'] - 原数组不变
// 从索引2开始到结尾
const result2 = fruits.slice(2)
console.log(result2) // ['orange', 'grape', 'kiwi']
// 负数索引:从倒数第2个到倒数第1个
const result3 = fruits.slice(-2, -1)
console.log(result3) // ['grape']
// 场景1:数组浅拷贝
const original = [1, 2, 3, 4, 5]
const copy = original.slice()
console.log(copy) // [1, 2, 3, 4, 5]
console.log(copy === original) // false - 不是同一个数组
// 场景2:获取数组的一部分
const searchResults = ['result1', 'result2', 'result3', 'result4', 'result5']
const firstThree = searchResults.slice(0, 3) // 前3条结果
const lastTwo = searchResults.slice(-2) // 后2条结果
// 场景3:分页处理
function getPage(array, pageSize, pageNumber) {
const start = (pageNumber - 1) * pageSize
const end = start + pageSize
return array.slice(start, end)
}
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(getPage(data, 3, 1)) // [1, 2, 3] - 第1页
console.log(getPage(data, 3, 2)) // [4, 5, 6] - 第2页
// 从索引1开始删除2个元素
const deleted = fruits.splice(1, 2)
console.log(deleted) // ['banana', 'orange'] - 被删除的元素
console.log(fruits) // ['apple', 'grape', 'kiwi'] - 原数组被修改
// 删除最后一个元素
const lastItem = fruits.splice(-1, 1)
console.log(lastItem) // ['kiwi']
console.log(fruits) // ['apple', 'grape']
const numbers = [1, 2, 5, 6]
// 在索引2处插入3和4(删除0个元素)
numbers.splice(2, 0, 3, 4)
console.log(numbers) // [1, 2, 3, 4, 5, 6]
// 在开头插入0
numbers.splice(0, 0, 0)
console.log(numbers) // [0, 1, 2, 3, 4, 5, 6]
const colors = ['red', 'green', 'blue', 'yellow']
// 从索引1开始,删除2个元素,并插入新元素
const replaced = colors.splice(1, 2, 'purple', 'orange')
console.log(replaced) // ['green', 'blue'] - 被替换的元素
console.log(colors) // ['red', 'purple', 'orange', 'yellow']
原始类型包装器
- new 包装器(值):返回的是一个对象
- 包装器(值):返回的是一个原始类型
Number
静态成员
- isNaN 检测指定参数是否为 NaN。
- isFinite 检测指定参数是否为无穷大
- isInteger:判断一个数据是否是整数
- parseFloat: 将一个数据转换为小数
- parseInt:将以一个数据转换为整数,直接舍去小数部分
parseInt、parseFloat要求参数是一个字符串,如果不是字符串,则会先转换为字符串。 从字符串开始位置进行查找,找到第一个有效的数字进行转换,如果没有找到,则返回NaN,左右空白字符会忽略
parseInt,可以传入第二个参数,表示将给定的字符串,识别为多少进制。
上面都是类似用下面方法调用 Number.isFinite(1);
实例成员
- toFixed方法:会有四舍五入
- toPrecision:以指定的精度返回一个数字字符串
var a = 111;
a.toFixed(2);
Boolean
String
静态成员
- fromCharCode:通过unicode编码创建字符串
实例成员
- length:字符串长度
字符串是一个伪数组
JavaScript 常见字符串方法总结
-
charAt:返回指定位置的字符。- 示例:
'hello'.charAt(1)返回'e'。
- 示例:
-
charCodeAt:返回指定位置字符的 Unicode 编码。- 示例:
'hello'.charCodeAt(1)返回101(字母'e'的 Unicode 编码)。
- 示例:
-
concat:连接两个或更多字符串,并返回新的字符串。- 示例:
'hello'.concat(' world')返回'hello world'。
- 示例:
-
includes:检查字符串中是否包含指定的子字符串。- 示例:
'hello'.includes('ell')返回true。
- 示例:
-
endsWith:判断字符串是否以指定的子字符串结尾(区分大小写)。- 示例:
'hello'.endsWith('lo')返回true。
- 示例:
-
startsWith:检查字符串是否以指定的子字符串开头。- 示例:
'hello'.startsWith('he')返回true。
- 示例:
-
indexOf:返回指定子字符串在字符串中首次出现的位置。- 示例:
'hello'.indexOf('l')返回2。
- 示例:
-
lastIndexOf:从后向前搜索字符串,返回子字符串最后出现的位置。- 示例:
'hello'.lastIndexOf('l')返回3。
- 示例:
-
padStart:在当前字符串的开头填充指定的字符,直到字符串达到给定的长度。- 示例:
'5'.padStart(3, '0')返回'005'。
- 示例:
-
padEnd:在当前字符串的结尾填充指定的字符,直到字符串达到给定的长度。- 示例:
'5'.padEnd(3, '0')返回'500'。
- 示例:
-
repeat:复制字符串指定次数,并将它们连接在一起返回。- 示例:
'ha'.repeat(3)返回'hahaha'。
- 示例:
-
slice:从某个位置开始,取到某个位置(可以是负数)。- 示例:
'hello'.slice(1, 3)返回'el'。
- 示例:
-
substr:从某个位置开始,取指定长度的字符(位置可以是负数)。- 示例:
'hello'.substr(1, 3)返回'ell'。
- 示例:
-
substring:从某个位置取到某个位置,不能为负数,参数顺序可以调换。- 示例:
'hello'.substring(1, 3)返回'el'。
- 示例:
-
toLowerCase:将字符串转换为小写。- 示例:
'HELLO'.toLowerCase()返回'hello'。
- 示例:
-
toUpperCase:将字符串转换为大写。- 示例:
'hello'.toUpperCase()返回'HELLO'。
- 示例:
-
split:根据指定分隔符将字符串分割为数组。- 示例:
'a,b,c'.split(',')返回['a', 'b', 'c']。
- 示例:
-
字符串索引:使用
字符串[index]直接获取指定位置的字符。- 示例:
'hello'[1]返回'e'。
- 示例:
Math对象
提供了一系列与数学相关的成员
常量:永远不会变化的数据。常量一般命名时所有字母大写,如果有多个单词,用下划线分割。
- random方法: 产生一个0~1之间的随机数
- PI属性:得到圆周率
- abs方法:求绝对值
- floor方法:对一个数向下取整
- ceil方法:对一个数向上取整
- max方法:得到一组数字的最大值;如果无参,得到-Infinity
- min方法:得到一组数字的最小值;如果无参,得到Infinity
- pow方法:求一个数字的幂次方
- round方法:得到一个四舍五入的整数
Date构造函数
术语
- 时间单位
年(year) 月(month) 日(date) 小时(hour) 分钟(minute) 秒(second) = 1000ms 毫秒(millisecond,ms) = 1000 us 微秒(microsecond,us) = 1000 ns 纳秒(nanosecond,ns)
- UTC和GMT
世界划分为24个时区,北京在东8区,格林威治在0时区。
GMT:Greenwish Mean Time 格林威治世界时。太阳时,精确到毫秒。 UTC:Universal Time Coodinated 世界协调时。以原子时间为计时标准,精确到纳秒。
UTC和GMT之间误差不超过0.9秒
GMT+0800 东8区
- 时间戳
数字
1970-1-1 凌晨 到 某个时间 所经过的毫秒数
创建时间对象
- 直接调用函数(不适用new),忽略所有参数,直接返回当前时间的字符串。
- new Date(): 创建日期对象
- 无参,当前时间
- 1个参数,参数为数字,表示传入的是时间戳
- 两个参数以上,分别表示:年、月、日、时、分、秒、毫秒
注意:月份的数字从0开始计算,所以getMonth() + 1 才是真实的月份
如果缺失参数,日期部分默认为1,时分秒毫秒默认为0。
月、日、时、分、秒、毫秒,均可以传递负数,如果传递负数,会根据指定日期进行计算。
实例成员
-
getDate方法:得到日期部分
-
getDay方法:得到星期几,0表示星期天
-
getFullYear方法:得到年份
-
getHours方法:得到小时部分
-
getMinutes方法:得到分钟部分
-
getSeconds方法:得到秒部分
-
getMilliseconds方法:得到毫秒部分
-
getTime方法:得到时间戳
-
getMonth方法:得到月,从0开始计算
-
setDate方法:设置日期
-
setMonth方法:设置月份
-
setFullYear方法:设置年
-
setMinutes方法
-
setSeconds方法
-
setMilliseconds方法
-
setTime方法:重新设置时间戳
-
toDateString方法:将日期部分转换为可读的字符串。
-
toISOString方法:将整个对象转换为ISO标准的字符串格式。
-
toLocaleDateString方法:根据当前系统的地区设置,将日期部分转换为可读的字符串
-
toLocaleString方法:根据当前系统的地区设置,将整个日期对象转换为可读的字符串
-
toLocaleTimeString方法:根据当前系统的地区设置,将时间部分转换为可读的字符串
日期的运算
日期对象重写了Object中的valueOf方法,返回的是一个数字,表示时间戳
因此,日期对象可以进行数学运算
正则表达式
正则表达式是国际标准,跨越语言
正则表达式是一个规则,用于验证字符串。
基础
- 字面量匹配
规则中直接书写字面量字符
- 特殊字符
. 查找单个字符,除了换行和行结束符。
^ 匹配字符串的开始。
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
3. 转义符 有时需要将特殊含义的符号转化为没有特殊含义,或者没有特殊含义的转化特殊的含义的字符。
\n 匹配一个换行符
\r 匹配一个回车符
\t 匹配一个制表符
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符
\b 匹配一个单词边界,即字与空格间的位置。
\B 非单词边界匹配。
\d 匹配任意一个阿拉伯数字(0 到 9)
\D 匹配非数字
\w 匹配字母、数字、下划线。等价于 [A-Za-z0-9_]
\W 和\w相反
\u 按照Unicode去匹配
转义符可以将特殊字符转义
- 字符集
[ABC] 作用是匹配A字符,B字符,C字符,注意不是匹配 ABC 字符
[^ABC] 作用是匹配除了ABC以外的所有字符
[A-Z] 作用[A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母。
[0-9] 作用是匹配数字。
匹配中文: [\u4e00-\u9FA5] 根据Unicode 匹配中文
- 量词
前面的规则出现的次数
* 出现0次或者多次
+ 出现一次或者多次
? 出现0次或者一次
{n}: 匹配n个
{n,}: 匹配>=n个
{n,m}: 匹配n-m个
\d[a-z]{3} 只能匹配 1aaa 这种类型的,3代表的[a-z]出现三次 (\d[a-z]){3}代表 1abc1abc1abc
6.或者
多个规则之间,使用或者 |,表示多个规则任选其一。
abc|123 abc或者123 都能匹配
JS中的应用
js中,正则表达式表现为一个对象,该对象是通过构造函数RegExp
创建正则对象
- 字面量模式
var reg = /\d+?/;
字面量创建的方式是 / / 里面写正则表达式
对应的标志位有 g:全局匹配 找到所有的匹配项,而不是在第一个匹配后停止 i 忽略大小写 m 多行,将开始和结束标志符在多行上工作 u
- 构造函数模式
var reg = /\d+?/g;
var reg1 = new RegExp("\d+?","g");
var reg2 = new RegExp(reg);
如果要放多个标志位
var reg = /\d+?/gi;
var reg1 = new RegExp("\d+?","gi");
var reg2 = new RegExp(reg);
正则实例成员
拿到正则表达式对象,可以通过取正则表达式对象的属性去获取一些东西。
- global 全局匹配:找到所有的匹配项,而不是在第一个匹配后停止
- ignoreCase 忽略大小写
- multiline 多行,将开始和结束标志符在多行上工作。
- source
- test方法:验证某个字符串是否满足规则
- exec方法:execute,执行匹配,得到匹配结果。得到的是一个对象
正则表达式,默认情况下,适用贪婪模式 在量词后,加上?,表示进入非贪婪模式
什么叫贪婪模式还是非贪婪模式?
比方说 /\d+/g 对于字符串 "1234abc123aaa"应该怎么处理呢?
每次如果只匹配 1,2,3,4是满足的正则表达式,也可能一次直接匹配 1234。一次直接匹配到1234 是贪婪模式,而每次只匹配到1,2,3,4就是非贪婪模式。
下面来讲讲全局匹配和不是全局匹配是怎么匹配的?
var reg = /\d+?/g;
var s = "1234abc123aaa";
console.log(s, reg.lastIndex, reg.test(s), reg.lastIndex);
console.log(s, reg.lastIndex, reg.test(s), reg.lastIndex);
console.log(s, reg.lastIndex, reg.test(s), reg.lastIndex);
console.log(s, reg.lastIndex, reg.test(s), reg.lastIndex);
console.log(s, reg.lastIndex, reg.test(s), reg.lastIndex);
console.log(s, reg.lastIndex, reg.test(s), reg.lastIndex);
全局匹配是从第一位开始匹配,匹配到了后停止,下一次还是从上一次匹配结束的位置开始,直到最后匹配不到为止。这种结束后再从第一个位置开始匹配。 而非全局匹配是每次开始去匹配。
所以可以用下面的代码来计算匹配的次数
var n = 0;
while (reg.test(s)) {
n++;
}
console.log(`匹配了${n}次`);
var reg = /\d+/g;
var s = "1234abc123aaa";
//得到所有的匹配结果和位置,下面相当于 window.result = reg.exec(s),因为是全局搜索模式,所以可以获取到匹配的次数。
while (result = reg.exec(s)) {
console.log(`匹配结果:${result[0]},出现位置:${result.index}`);
}
字符串对象中的正则方法
- split
- replace
- search
- match
进阶
捕获组
用小括号包裹的部分叫做捕获组,捕获组会出现在匹配结果中
var reg = /(\d[a-z])([a-z]+)/g;
var s = "2afsdf-5fdgdfg-9asddf";
while (result = reg.exec(s)) {
console.log(result);
}
捕获组的用处是整个大块的匹配到了,把匹配到一整块的一小部分也拿到了,这时候如果要处理这一块就方便了。
捕获组可以命名,叫做具名捕获组
正常的捕获组
var s = "2015-5-1, 2019-6-19, 2000-04-28";
//得到每一个日期,并得到每个日期的年月日
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
while (result = reg.exec(s)) {
//捕获组 ,捕获组1,捕获组2,捕获组3
console.log(result[0],result[1],result[2],result[3]);
}
由于result[1],result[2]这样可读性不好,要使用用捕获组命名。 在捕获组前面使用 ?<名字> 来进行命名
var s = "2015-5-1, 2019-6-19, 2000-04-28";
//得到每一个日期,并得到每个日期的年月日
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
while (result = reg.exec(s)) {
//捕获组 ,捕获组1,捕获组2,捕获组3
console.log(result[0],result[1],result[2],result[3]);
}
var s = "2015-5-1, 2019-6-19, 2000-04-28";
//得到每一个日期,并得到每个日期的年月日
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
while (result = reg.exec(s)) {
//捕获组 ,捕获组1,捕获组2,捕获组3
console.log(result[0],result[1],result[2],result[3]);
}
var s = "2015-5-1, 2019-6-19, 2000-04-28";
//得到每一个日期,并得到每个日期的年月日
var reg = /(?<year>\d{4})-(?<month>\d{1,2})-(?<day>\d{1,2})/g;
while (result = reg.exec(s)) {
console.log(result[0],result.groups.year,result.groups.month,result.groups.day);
}
通过groups.名字去取值
非捕获组 有时我们小括号只想当做一个整体,而不想捕获的时候,我们使用非捕获组,非捕获组我们使用 (?: xxxxx) ,在小括号开始的地方使用?:.
var s = "2015-5-1, 2019-6-19, 2000-04-28";
//得到每一个日期,并得到每个日期的年月日
var reg = /(?:\d{4})-(?:\d{1,2})-(\d{1,2})/g;
while (result = reg.exec(s)) {
console.log(result);
}
字符串中replace 使用捕获组
2 表示第二个捕获组 $3表示第三个捕获组
var s = "2015-5-1,- 2019-6-19,- 2000-04-28";
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
s = s.replace(reg, "$1/$2/$3")
console.log(s);
反向引用
在正则表达式中,使用某个捕获组,\捕获组编号
下面的意思就是说先匹配两个数字,然后再重复捕获组1一次,这是整个正则匹配的条件。
var reg = /(\d{2})\1/;
var s = "1313";
console.log(reg.test(s));
正向断言(预查)
检查某个字符后面的字符是否满足某个规则,该规则不成为匹配结果,并且不称为捕获组
负向断言(预查)
检查某个字符后面的字符是否不满足某个规则,该规则不成为匹配结果,并且不称为捕获组
错误处理
JS中的错误分为:
- 语法错误:会导致整个脚本块无法执行。
- 运行错误
- 运行报错:会导致当前脚本块后续代码无法执行
- 运行结果不符合预期
调试错误
-
控制台打印
-
断点调试 断点调试可以分为两种,一种是chrome 自带的调试工具,具体文档 chrome 官方调试文档 还有一种是使用VsCode 去调试。
抛出错误
错误在js中本质上是一个对象,抛出错误的语法为:
throw 错误对象;
错误对象的构造函数为Error
捕获错误
try{
//代码块1
}
catch(错误对象){
//代码块2
}
finally{
//代码块3
}
当运行代码1的时候,如果发生错误,立即停止代码1的执行,转而执行代码2,错误对象为抛出的错误对象。无论代码1和代码2是否,最终都将执行代码3