数组
数组简介
数组也是一个对象,和普通的对象功能类似,也是用来存储一些值的,不同的是普通对象是使用字符串作为属性值的,而数组是使用数字来作为索引操作元素的
创建数组对象
获取数组的长度:
对于连续的数组,使用length属性来获取数组的长度(元素的个数)
对于非连续的数组,使用length属性会获取到数组的最大索引加1
修改数组的长度:
如果修改的length大于原长度,则多出部分会空出来
如果修改的length小于原长度,则多出的元素会被删除
//创建数组对象
var arr = new Array();
//使用typeof检查一个数组时,会返回object
//console.log(typeof arr) object
//向数组中添加元素
arr[0] = 10;
arr[1] = 11;
arr[2] = 12;
//读取数组中的元素
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
//获取数组的长度
console.log(arr.length);
//修改数组的长度
arr.length = 10;
//向数组的最后一个位置添加元素
arr[arr.length] = 15;
数组字面量
使用字面量来创建数组
//使用字面量来创建数组
var arr = [];
//使用字面量来创建数组时,可以在创建时就指定数组中的元素
var arr = [1,2,3,4,5];
//使用构造函数来创建数组时,也可以同时添加元素,将要添加的元素作为构造函数的参数进行传递
var arr = new Array(1,2,3,4,5);
//字面量
var arr1 = [10]; //创建一个数字,数组中只有一个元素
var arr2 = new Array(10);//创建长度为10的数组
console.log(arr1);// 10
console.log(arr2);//,,,,,,,,, 长度为10
//数组中的元素可以是任意的数据类型,也可以是对象,也可以是函数,也可以放数组
var arr3 = ["hello",1,true,null,undefined,{
name:'猪八戒'},function(){
alert(2)},[1,2,3]]
var obj = {
name:'孙悟空'};
arr3.[arr.length] = obj;
创建一个数字,数组中只有一个元素var arr1 = [10];
创建长度为10的数组var arr2 = new Array(10);
数组的四个方法
- push():
向数组的末尾中添加一个或者多个元素,并返回数组的新的长度
可以将要添加的元素作为方法的参数传递,这样这些元素将会自动添加到数组的长度
该方法会将数组新的长度作为返回值返回。
var arr = ['孙悟空','猪八戒','沙和尚']
var result = arr.push('唐僧','蜘蛛精','白骨精');
console.log(arr)//孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精,白骨精
console.log(result);//6
- pop():
该方法可以删除数组中的最后一个元素,调用一次删除一次
该方法会将被删除的元素作为返回值返回
var arr = ['孙悟空','猪八戒','沙和尚']
var result = arr.push('唐僧','蜘蛛精','白骨精');
result = arr.pop();
console.log(arr)//孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精
console.log(result);//白骨精
- unshift():
向数组开头添加一个或多个元素,并返回新的数组长度;
像前面插入元素以后,其他元素的索引回依次调整
var arr = ['孙悟空','猪八戒','沙和尚']
var result = arr.push('唐僧','蜘蛛精','白骨精');
result = arr.unshift('牛魔王');
console.log(arr)//牛魔王,孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精
console.log(result);//7
- shift()
可以删除数组的第一个元素并将被删除的元素作为返回值返回
数组的遍历(forEach)
遍历数据就是将数组中的所有的元素都取出来
for(var i=0;i<arr.length;i++){
cosole.log(arr[i])
}
也可以调用forEach()方法去遍历(这个方法只支持IE8以上的浏览器)
forEach()方法需要一个函数作为参数,一般不传普通函数进去,因为传普通函数,就还是相等于在全局作用域中定义了一个函数,因此一般传进去的是匿名函数
var arr = ['孙悟空','猪八戒','沙和尚']
arr.forEach(function(){
console.log('hello')
})
此时,直接打印出了3次hello
- 像这种函数,由我们创建但是不由我们调用的,我们称为回调函数。可以简单理解,这种函数由浏览器去调用,我们只是给浏览器传过去
- 数组中有几个元素,函数就执行几次。每次执行时,浏览器就会将遍历到的元素以实参的形式传递进来。
var arr = ['孙悟空','猪八戒','沙和尚']
arr.forEach(function(a,b,c){
console.log('a='+a)
console.log('b='+b)
console.log('c='+c)
})
输出:
a = ‘孙悟空’;
a = ‘猪八戒’;
a = ‘沙和尚’ ;
b = 0;
b = 1;
b =2;
c=孙悟空,猪八戒,沙和尚;
c=孙悟空,猪八戒,沙和尚
c=孙悟空,猪八戒,沙和尚
- 浏览器会在回调函数中传递三个参数:
- 第一个参数,就是当前正在遍历的参数(value)
- 第二个参数,就是当前正在遍历的元素的索引 (index)
- 第三个参数,就是正在遍历的数组(obj)
splice和slice
slice:
- slice()方法可以从已有的数组中返回选定的元素
- 语法:arrayObject.slice(start,end)
- 参数:start:必需,规定从何处开始选取,截取开始的位置索引,包含开始索引。end:截取结束的位置的索引,不包含结束索引。可以省略不写,此时会截取从开始索引往后的所有元素。end也可以传递一个负值,如果传递一个负值,则从后往前计算。
- 该方法不会改变原数组,而是将截取到的元素封装到一个新数字中返回
splice:
- 可以用于删除,插入,替换数组中的指定元素
- 使用splice()会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回
- 参数:第一个:表示开始位置的索引;第二个:表示删除的数量;第三个及以后:可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边。
数组的剩余方法
concat:
- concat()可以连接两个或者多个数组,并将新的数字返回
- 该方法不会对原数组产生影响
- 不仅可以传数组,也可以传元素
var result = arr.concat(arr1,arr2,"牛魔王","铁扇公主");
join:
- 该方法可以将数组转换为一个字符串
- 不会对原数组产生影响,而是将转换后的字符串作为结果返回
- 在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符
arr = ["孙悟空","猪八戒","沙和尚"]; result = arr.join('hello')
;输出'孙悟空hello猪八戒hello沙和尚'
- 如果不指定连接符,则默认使用逗号作为连接符。如果不想要连接符,则使用一个空串。
arr.join('')
reverse:
- 该方法用来反转数组
- 会直接修改原数组
sort:
- 可以用来对数组中的元素进行排序
- 也会影响原数组
- 默认会按照Unicode编码进行排序,即使对应纯数字的数字,使用sort()排序时,也会按照Unicode编码来排序,因此,对于对数字进行排序时,可能会得到错误的信息。
- 我们可以自己指定排序的规则,可以在sort()添加一个回调函数,来指定排序规则。回调函数中需要定义两个形参,浏览器将会分别使用数组中的元素作为实参去调用回调函数;使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前面
- 如果返回一个大于0的值,则元素会交换位置;如果返回一个小于0的值,则元素位置不变;如果返回一个等于0的值,则元素相等,位置不变
arr = [5,4,2,1,3,6,8,7]
arr.sort(function(a,b){
//前面的大
if(a > b){
return 1;
}else if(a < b){
return -1;
}else{
return 0;
}
})
等同于
arr = [5,4,2,1,3,6,8,7]
arr.sort(function(a,b){
//升序排列
return a - b;
})
结论:升序:a-b;降序:b-a
函数(补充)
call()和apply()
- 这两个方法都是函数对象的方法,需要通过函数对象来调用
- 当函数调用call()和apply()都会调用函数执行
function fun(){
alert("我是fun函数!");
}
fun.aaply();
fun.call();
- 在调用call和apply()可以将一个对象指定为第一个参数。此时这个对象将会成为函数执行的this
- call()方法可以将实参在对象之后依次传递
fun.call(obj,2,3)
;而apply()方法需要将实参封装到一个数组中统一传递fun.apply(obj,[2,3])
this总结:
- 以函数形式调用时,this是window;
- 以方法的形式调用时,this是调用方法的对象
- 以构造函数的形式调用时,this是新创建的对象
- 使用call和apply调用时,this指定的那个对象
arguments
在调用函数时,浏览器每次都会传递两个隐含的参数
- 函数的上下文对象this
- 封装实参的对象arguments
arguments:
- arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度
- 在调用函数时,我们所传递的实参都会封装到arguments中
- arguments.length可以用来获取实参的长度
- 即使不定义形参也可以通过arguments来使用实参。arguments[0]表示第一个实参
- arguments有一个callee属性,这个属性对象一个函数对象,就是当前正在指向的函数的对象。
function fun(){
console.log(arguments);
console.log(arguments instanceof Array);//false
console.log(Array.isArray(arguments));//false
console.log(arguments[1]);//2
console.log(arguments.callee);//打印出fun函数
}
fun(1,2);
内嵌对象:Date对象
- 在JS中使用Data对象来表示时间
- 如果直接使用构造函数创建一个对象,则会封装当前代码的时间。下面例子中:就是
let d = new Date()
执行的时间
let d = new Date();
console.log(d);//打印出当前时间
- 创建一个指定的时间对象:需要在构造函数中传递一个表示时间的字符串作为参数
let d2 = new Data('12/03/2016 11:10:30')
- 日期格式:月份/日/年时:分:秒
方法:
- getDate():获取当前日期对象是几日(1-31),一个月中的某一天
- getDay():从Date对象返回一周中的某一天(0-6),0表示周日
- getMonth():获取当前时间对象的月份(0-11)从0开始,0表示一月,如果想要正常转化,需要加一
- getFullYear():获取当前事件对象的四位数字的年份
- getTime():获取当前对象的时间戳。时间戳是指格林威治标准时间1970年1月1日0时0分0秒到当前时间所花的毫秒数(1秒等于1000毫秒)。计算机为了统一时间单位,因此计算机底层在保存时间时使用的都是时间戳。
- 获取当前的时间戳:
time = Date.now()
应用:
利用时间戳来测试代码的执行的性能
//获取当前的时间戳
let start = Date.now();
for(let i=0;i<100;i++){
console.log(i);
}
let end = Date.now();
console.log("执行了"+(end - start)+'毫秒');
Math
- math和其他对象不同,他不是一个构造函数,属于一个工具类不用创建对象,他里面封装了数学运算相关的属性和方法
- Math.PI表示圆周率
- Math.abs()可以用来计算一个数的绝对值
console.log(Math.abs(-1)) //1
- Math.ceil()可以对一个数进行向上取整,小数位只要有值就自动进一
console.log(Math.ceil(1.001)) //2
- Math.floor()可以对一个数进行向下取整,小数位会被舍掉
console.log(Math.floor(1.99)) //1
- Math.round()可以对一个数进行四舍五入取整
console.log(Math.round(1.4)) //1
- Math.random()可以用来生成一个0-1之间的随机数,不会出现0和1;如果想生成一个0-10的随机数
console.log(Math.random()*10)
,如果想要生成一个整数console.log(Math.round(Math.random()*10))
- 生成一个x-y之间的随机数
Math.round(Math.random()*(y-x)+x)
- Math.max()可以获取多个数中的最大值。
Math.max(10,34,56,44)
; - Math.min()可以获取多个数中的最小值。
Math.min(10,34,56,44)
; - Math.pow(x,y)返回x的y次幂。
Math.pow(12,3)
; - Math.sqrt(x)对x进行开方运算
包装类
在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转化为对象
String():可以将基本数类型字符串转换为String对象
number():可以将基本数据类型的数字转化为Number对象
Boolean():可以将基本数据类型转化为Boolean对象
创建一个Number类型的对象
let num = new Number(3);
console.log(num)//3
console.log(typeof num)//object对象类型
既然是对象,就可以向其添加属性
num.hello = 'weewrqr';
console.log(num.hello);//weewrqr
当使用包装类创建两个对象,这两个对象并不相等
let num1 = new Number(3);
let num2 = new Number(3);
console.log(num1 == num2);//false
原因:两个对象相比较,比较的是内存地址
注意:在实际应用中不会使用基本数据类型的对象,如果使用基本数据类型的对象,在做一些比较时可能会带来不可预期的结果
let b = new Boolean(false);
if(b){
alert('我运行了')
}
结果:依然会弹出’我运行了’弹出框。因为b是一个对象,定义了就有值
包装类的使用情况:
一般来说方法和属性只能添加给对象,不能添加给基本数据类型,但是以下情况却不会报错
let s = 123;
s = s.toString();
console.log(s);//123
console.log(typeof s);//string
上述例子中,基本数据类型不仅调用了toString()方法,并且成功将number类型转化为string类型,这是因为当我们对一些基本数据类型的值去调用属性和方法时,浏览器会临时使用包装类将其转化为对象,然后再调用对象的属性和方法,调用完以后在将其转化为基本数据类型
let s = 123;
s = s.toString();
s.hello = '你好';
console.log(s.hello);//undefined
上述例子中打印出来undefined;浏览器临时使用包装类转化的对象是临时对象,在给s添加hello属性时,他将s临时转为一个对象,将属性添加到对象中去,属性添加完以后,对象就被销毁了。当打印s.hello时,会去读基本数据类型s中的hello属性,而基本类型不能保存属性,所以需要临时把s转换为字符串对象,然后去读hello属性,而转化前的s又没有该属性,因此为undefined。所以:每次调用,每次转化,转化完就销毁
字符串的方法
(主要是指String对象里的方法)
在底层字符串是以字符数组的形式保存的,比如:'hello’在底层的保存形式为[‘h’,‘e’,‘l’,‘l’,‘o’];因此:let str = 'hello'; console.log(str.length)//5;console.log(str[1];//e)
charAt()
- 可以返回字符串中指定位置的字符
- 根据索引获取指定的字符
let str = 'hello atguigu'
let result = str.charAt(6);
console.log(result);//A
charCodeAt()
- 获取指定位置字符的字符编码(Unicode编码)
let str = 'hello atguigu'
let result = str.charCodeAt(6);
console.log(result);//97
fromCharCodeAt()
- 可以根据字符编码去获取字符;
- 使用的是字符对象去调用该方法
let result = String.fromCharCode(97);
console.log(result);//a
concat()
- 可以用来连接两个或多个字符串
- 作用和+一样
- 对原字符串没有影响,输出str,依旧是hello atguigu
let str = 'hello atguigu'
let result = str.concat('你好','再见')
console.log(result);//hello atguigu你好再见
indexof()
- 该方法可以检索一个字符串中是否含有指定内容
- 如果字符串中含有该内容,则会返回其第一次出现的索引。
- 如果没有找到指定的内容,则返回-1
- 可以指定一个第二个参数,该参数指定开始查找的位置
let str = 'hello atguigu';
let result1 = str.indexOf('a');
console.log(result1);//6
let result2 = str.indexOf('a',1)//6
lastIndexOf()
- 该方法的用法和indexOf一样,不同的是indexOf()是从前往后找,而lastIndexOf()是从后往前找
- 也可以指定开始查找的位置
let str = 'hello atguigu';
let result1 = str.lastIndexOf('o');
console.log(result1);//4
let result2 = str.indexOf('a',4)//o
slice()
- 可以从指定字符串中截取指定的内容
- 不会影响到源字符串,而是将截取到的内容返回
- 参数:第一个:开始位置的索引(包括开始位置);第二个:结束位置的索引(不包括结束位置)
- 如果省略第二个参数,则会截取到后面所有的
- 也可以传递一个负数作为参数,负数的话将会从后面计算,-1表示结束到倒数第一个,不包括倒数第一个,因此没有k
let str = 'abcdefghijk';
let result = str.slice(1,4)
console.log(result);//bcd
let result1 = str.slice(1)
console.log(result1);//bcdefghijk
let result2 = str.slice(1,-1);
console.log(result2);//bcdefghij
substring()
- 可以用来截取一个字符串,和slice类似
- 参数:第一个:开始截取位置的索引(包括开始位置)第二个:结束位置的索引(不包括结束位置)
- 与splice不同的是这个方法不接受负值作为参数,如果传递了一个负值,则默认使用0
- 会自动调整参数的位置,如果第二个参数小于第一个,则自动交换位置
- str.substring(3,-1)==str.substring(3,0)==str.substring(0,3);所以是abc
let str = 'abcdefghijk';
let result1 = str.substring(0,2);
console.log(result1)//ab
let result2 = str.substring(3,-1);//abc
console.log(result2)
substr()
- 用来截取字符串
- 参数:第一个:截取开始位置的索引;第二个:截取的长度
let str = 'abcdefghijk';
let result1 = str.substr(3,2);
console.log(result1)//de
split()
- 可以将一个字符串拆分为一个数组
- 参数:需要一个字符串作为参数,将会根据该字符串去拆分数组
- 如果传递一个空串作为参数,将会根据该字符串去拆分数组
let str = 'abc,def,ghi,jk';
let result = str.split(',');
console.log(result[0]);
let str1 = 'abcdefghijk';
let result1 = str1.split('');
console.log(result1);// ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
toUpperCase()
- 可以将一个字符串转化为大写并返回
- 不会影响到原变量
toLowerCase()
- 可以将一个字符串转化为小写并返回
- 不会影响到原变量
正则表达式
正则表达式用于定义一些字符串的规则:
- 计算机可以根据正则表达式,来检查一个字符串是否符合规则,获取将字符串中符合规则的内容提取出来
创建正则表达式的对象:
- 语法:var 变量 = new RegExp(‘正则表达式’,‘匹配模式’);
- 使用typeof检查正则对象,会返回object
- 在构造函数中可以传递一个匹配模式作为第二个参数。可以是:i 忽略大小写 g 全局匹配模式
正则表达式的方法:
- test();
- 使用这个方法可以检查一个字符串是否符合正则表达式的规则
- let reg = new RegExp(‘a’)用于检查一个字符串中是否含有小写的a
let reg = new RegExp('a','i');
let str = 'a';
let result = reg.test(str);
console.log(result);//true
使用字面量来创建正则表达式
- 语法:let 变量 = /正则表达式/匹配模式
let reg = /a/i;
let str = 'a';
let result = reg.test(str);
console.log(result);//true
创建一个正则表达式,检查一个字符串中是否有a或b:使用|表示或者的意思
let reg = /a|b/;
console.log(reg.test('bcd'))//true
创建一个正则表达式,检查一个字符串中是否有字母:[]里的内容也是或的关系,[ab]==a|b。[a-z]任意小写字母;[A-Z]任意大写字母;[A-z]任意字母
let reg = /[a-z]/;
console.log(reg.test('bcd'))//true
创建一个正则表达式,检查一个字符串中是否含有abc或adc或aec
let reg = /a[bde]c/;
console.log(reg.test('aec'))//true
[^ ] 除了;[^ab] 除了ab;[^0-9] 除了数字
字符串和正则表达式
split()
- 可以将一个字符串拆分为一个数组
- 方法可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆字符串
- 这个方法及时不指定全局匹配,也会全部拆分
需求:根据任意字母来建字符串拆分
let str = '1a2b3c4d5e6f7g8h9i';
let result = str.split(/[A-z]/)
console.log(result);//['1', '2', '3', '4', '5', '6', '7', '8', '9', '']
search()
- 搜索字符串中是否含有指定内容
- 如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回-1;
- 可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
- 只会查找第一个,即使设置了全局匹配也没用
需求:搜索字符串中是否含有abc
let str = 'hello abc hello abc';
let result1 = str.search('abc');
console.log(result1)//6
let result2 = str.search('abcd');
console.log(result2)//-1
需求:搜索字符串中是否含有abc 或 aec 或afc
let str = 'hello abc hello aec afc';
let result1 = str.search(/a[bef]c/);
console.log(result1)//6
match()
- 可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
- 默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索了,我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容。
- 可以为一个正则表达式设置多个表达式,且顺序无所谓/[A-z]/ig == /[A-z]/gi
- match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果
需求:找到字符串中所有的字母
let str = '1a2b3c4d5e6f7g8h9i';
let result = str.match(/[A-z]/g);
let result2 = str.match(/[A-z]/ig);//即全局匹配又忽略大小写
console.log(result);//['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
replace()
- 可以将字符串中指定内容替换为新的内容
- 参数:1被替换的内容,可以接受一个正则表达式作为参数 2新的内容
- 默认只会替换第一个
let str = '1a2a3a4a5e6f7A8B9C';
let result1 = str.replace('a','@_@');
console.log(result1);//1@_@2a3a4a5e6f7A8B9C
let result2 = str.replace(/[a-z]/gi,'@_@');
console.log(result2);//1@_@2@_@3@_@4@_@5@_@6@_@7@_@8@_@9@_@
let result3 = str.replace(/[a-z]/gi,'');
console.log(result3);//123456789
正则表达式语法
量词:
- 通过量词可以设置一个内容出现的次数
- {n}正好出现n次
- 量词只对它前面的一个内容起作用/(ab{3})/:找abbb的,如果想找连续的ababab,则/(ab){3}/
- /ab{1,3}c/意思为找abc,abbc,abbbc。b出现一次到三次
- /ab{3,}c/意思为b可以出现三次及以上
- {m,n}出现m-n次
- {m,}出现m次以上
- +至少一个,相当于{1,}
- *0个或多个,相当于{0,}
- ?0个或一个,相当于{0,1}
- ^ 表示开头
- $ 表示结尾
- . 表示任意字符
- 在正则表达式中使用\作为转义字符,.表示.;\表示\
需求:创建一个正则表达式来检查一个字符串中是否含有aaa(/aaa/ == /a{3}/)
let reg = /aaa/;
console.log(reg.test('aaabs'))//true
let reg1 = /a{3}/;
console.log(reg1.test('aaabs'))//true
需求:检查一个字符串是否以a开头
let reg = /^a/ //匹配开头的a
let reg1 = /a$/ //匹配结尾的a
let reg2 = /^a$/ //只能有一个a
let reg3 = /^|a$/ //以a开头或者以a结尾
console.log(reg.test('abc'))//true
console.log(reg1.test('abc'))//false
console.log(reg2.test('abc'))//false
需求:创建一个正则表达式,用来检查一个字符串是否是一个合法手机号。手机号规则:11位;第一位以1开头;第二位3-9任意数字;三位以后任意数字9个
let phoneStr = '13454563656';
let phoneReg = /^1[3-9][0-9]{9}$/
console.log(phoneReg.test(phoneStr));//true
需求:检查字符串中是否含有.
let reg =/./;
let reg1 = /\./;
console.log(reg.test('s'))//true
console.log(reg1.test('s'))//false
需求:检查字符串中是否含有\
let reg1 = /\\/;
console.log(reg1.test('s\\'))//true