#### string.charAt(下标);
作用:用于获取指定位置的字符。
var str = "刘德华"; var ok = str.charAt(2); console.log(ok); //输出华(注意字符串从0开始)
作用:返回指定位置的字符的 Unicode 编码。
var str = "刘德华";var ok = str.charCodeAt(2);console.log(ok); //输出21326
查找指定字符在字符串中第一次出现的位置,如果没有找到就返回-1
var str = "亲爱的大家好,欢迎加入js大家庭。";console.log(str.indexOf("大")); //返回3console.log(str.indeOf("php")); //返回-1
查找指定字符在字符串中最后一次出现的位置,如果没有找到就返回-1。
var str = "亲爱的大家好,欢迎加入js大家庭。";console.log(str.lastIndexOf("大")); //返回13console.log(str.indeOf("php")); //返回-1
截取指定位置的字符【含头不含尾】,第二个参数没有就默认截取到末尾。如果不传参数,那就表示复制一份。修改的是数据的副本,对原数据没有影响。
var str = "亲爱的大家好,欢迎加入js大家庭。";console.log(str.slice(2)); //输出的大家好,欢迎加入js大家庭。console.log(str.slice(3,6));//输出大家好,可以理解为从第3个开始,截取3个字符,也就是str.slice(3,3+3);console.log(str);//输出亲爱的大家好,欢迎加入js大家庭。也就是slice修改的是数据的副本。console.log(str.slice(-5,-3));//输出s大
和slice作用相仿,但是注意区别(slice支持负数,substring不支持)。
var str = "亲爱的大家好,欢迎加入js大家庭。";console.log(str.substring(3));//输出大家好,欢迎加入js大家庭console.log(str.substring(3,3+3));//输出大家好
从指定位置开始截取指定个数字符,第二个参数不传,截取到末尾。
var str = "亲爱的大家好,欢迎加入js大家庭。";console.log(str.substr(3,6));//输出大家好,欢迎
将字符串全部变成大写(对原有字符串没有影响)。
var str = "AbcdEFghiJ";console.log(str.toUpperCase()); //输出ABCDEFGHIJconsole.log(str); //输出AbcdEFghiJ
将字符串全部转换成小写(对原有字符串没有影响)。
var str = "AbcdEFghiJ";console.log(str.toLowerCase()); //输出abcdefghijconsole.log(str); //输出AbcdEFghiJ
将字符串按照指定分割符分割成几部分变成数组,分隔符不作输出,不传分隔符那么就直接变成数组的一个元素,该属性方法对原有字符串没有影响。
var str = "亲爱的大家好,欢迎加入js大家庭。";console.log(str.split("大"));//输出["亲爱的","家好,欢迎加入js","家庭。"]console.log(str.split());//输出["亲爱的大家好,欢迎加入js大家庭。"]console.log(str);//输出亲爱的大家好,欢迎加入js大家庭。
将匹配到的内容替换成指定的字符串(找到一处内容替换后即返回),对原有字符串没有影响。
var str = "亲爱的大家好,欢迎加入js大家庭。";console.log(str.replace("大","小"));//输出亲爱的小家好,欢迎加入js大家庭。console.log(str);//输出亲爱的大家好,欢迎加入js大家庭。
查找需要的内容在文本中第一次出现的位置,如果没有找到,就返回-1,和indexOf()相似,不同处在于可以与正则的配合。
var str = "亲爱的大家好,欢迎加入js大家庭。";console.log(str.search("大"));//输出3console.log(str.search("1"));//输出-1
这是一个全局的方法,之所以归类到Number下,是因为经常与检测数值一起使用。该方法用于检测数据是否不是一个数字。
var num1 = 20;console.log(isNaN(num1));//falsevar num2 = "20";console.log(isNaN(num2));//false(会自动尝试进行转换)var num3 = "20人";console.log(isNaN(num2));//falsevar num4 = "人20";console.log(isNaN(num4));//true
将数字进行四舍五入,保留指定小数位个数,对原有字符串没有影响,注意返回的是字符串。
var num1 = 42.54688;console.log(num1.toFixed(2));//42.55console.log(typeof num1.toFixed(2));//stringconsole.log(num1);//42.54688
将值合并到数组末尾,组成一个新数组,值可以是数组,也可以是单个元素,原有数组不受影响。
var a = [11,22,33];console.log(a.concat(44,55));//[11,22,33,44,55]console.log(a);//[11,22,33]
将数组按照连接符链接(连接符可忽略),没有连接符默认逗号(,)连接。该方法对原数组数据没有影响,返回的是一个新的连接字符串(string类型),另外,该方法与字符串方法split对应(split是按照字符分割成数组)。
var arr = ["20","30",true,NaN];console.log(arr.join());//返回字符串(string类型)形式 20,30,true,NaNconsole.log(arr);//返回数组 ["20", "30", true, NaN]console.log(arr.join(""));//返回字符串(string类型)形式 2030trueNaN
将数组变成字符串,对原有数据没有影响,逗号连接,但是不能传入连接符,没有join灵活。
var arr = ["20","30",true,NaN];console.log(arr.toString());//返回字符串(string类型)形式 20,30,true,NaNconsole.log(arr);//返回数组 ["20", "30", true, NaN]
不传参数:可以达到和concat不传参数一样的效果,即复制一个数组。
var arr = [44,55,66];var newArr = arr.slice();console.log(arr);//[44, 55, 66]console.log(newArr);//[44, 55, 66]newArr[0] = "你好";console.log(newArr);//["你好", 55, 66]console.log(arr);//[44, 55, 66]
Array.slice(开始下标):表示从开始下标位置起,截取到数组末尾。
var arr = [44,55,66,88];var newArr = arr.slice(2);console.log(arr);//[44, 55, 66,88]console.log(newArr);//[66,88]
Array.slice(开始下标,结束下标):表示从开始下表位置起,截取到结束下标-1的位置(含头不含尾)
var arr = [44,55,66,88];var newArr = arr.slice(2,3);console.log(arr);//[44, 55, 66,88]console.log(newArr);//[66]
在数组末尾添加数据,会改变原来的数组,这个方法返回数组的新长度。注意值可以为单个元素,也可以为数组,但是是原样插入,注意与array.concat()的区别。
var arr = [11,22]; console.log(arr.push());//2 var newLength = arr.push(33); console.log(newLength);//3 console.log(arr);//[11, 22, 33] newLength = arr.push([44,55]); console.log(newLength);//4 console.log(arr);//[11, 22, 33, Array(2)],二维数组。
删除数组末尾的一个元素,返回的是那个被删除的那个元素,会修改原数组。
var arr = [11,22,33];console.log(arr.pop());//33console.log(arr);//[11, 22]
在数组开头添加数据,会改变原来的数组,这个方法返回数组的新长度。注意值可以为单个元素,也可以为数组,但是是原样插入,注意与array.concat()的区别。
var arr = [11,22,33];console.log(arr.unshift());//3console.log(arr);//[11, 22,33]console.log(arr.unshift(44,true));//5console.log(arr);//[44, true, 11, 22, 33]console.log(arr.unshift(44,[55,66]));//7console.log(arr);//[44, Array(2), 44, true, 11, 22, 33],二维数组
删除数组开头的一个元素,返回的是那个被删除的那个元素,会修改原数组。
var arr = [11,22,33];console.log(arr.shift());//11console.log(arr);//[22,33]
对数组进行反转,返回修改后的数组,对原数组进行修改。
var arr = ["aa","bb","cc"];var newArr = arr.reverse();console.log(arr);//["cc", "bb", "aa"]console.log(newArr);//["cc", "bb", "aa"]
查找指定字符在数组中第一次出现的位置,如果没有找到就返回-1
var arr = ["111","222","333","111"];var arrPosition = arr.indexOf("111"); console.log(arrPosition);//0console.log(arr);//["111", "222", "333", "111"]var arrPosition = arr.indexOf("你好");console.log(arrPosition);//-1
遍历一个数组(IE9开始支持该方法),接收一个匿名函数,其中该匿名函数有三个形参,第一个表示数组的值,第二个表示数组的下标,第三个表示该数组名,没有对原数组进行修改,没有返回值(undefined)
var arr = [11,22,33];var arrLoop = arr.forEach(function(val,key,arrs){ val += 10; console.log(val);//21,32,43 注意三个值每个输出一行相互独立都为number类型});console.log(arr);//[11, 22, 33]console.log(arrLoop);//undefined
遍历一个数组(IE9开始支持该方法),接收一个匿名函数,其中该匿名函数有三个形参,第一个表示数组的值,第二个表示数组的下标,第三个表示该数组名,没有对原数组进行修改,需要有一个return返回值,有返回值,返回一个新的数组。
var arr = [11,22,33];var arrLoop = arr.map(function(val,key,arrs){ val += 10; console.log(val);//21,32,43 注意三个值每个输出一行相互独立都为number类型 return val;});console.log(arr);//[11, 22, 33]console.log(arrLoop);//[21, 32, 43]
给数组进行排序,返回排序后的数组,对原数组会进行修改。
var arr = [1,5,3,7,8,6];var arr2 = arr.sort();console.log(arr);//[1, 3, 5, 6, 7, 8]console.log(arr2);//[1, 3, 5, 6, 7, 8]
看似正确,但是要知道sort仅比较数组的第一位,所以直接使用这种方法是不可取的。可以通过一个匿名函数来解决:
var arr = [1,55,53,7,888,6545];var arr2 = arr.sort(function(a,b){return a-b});console.log(arr);//[1, 7, 53, 55, 888, 6545]console.log(arr2);//[1, 7, 53, 55, 888, 6545]
传入一个参数:从开始下标该位置开始截取到末尾,组成一个新数组返回,原有数组将丢弃截取到的内容,被修改掉。
var arr = ["天","下","第","一","帅"];var newArr = arr.splice(2);console.log(arr);//["天","下"]console.log(newArr);//["第","一","帅"]
传入两个参数:从开始下标该位置开始截取,按照删除个数截取。按数组形式返回截取的内容,原数组被修改掉。
var arr = ["天","下","第","一","帅"];var newArr = arr.splice(2,1);console.log(arr);//["天", "下", "一", "帅"]console.log(newArr);//["第"]
传入两个以上参数:从第三个参数开始,就表示在删除位置添加的元素,按数组形式返回截取的内容,原数组被修改掉。
var arr = ["天","下","第","一","帅"];var newArr = arr.splice(2,1,"哎呦","不错喔");console.log(arr);//["天", "下", "哎呦", "不错喔", "一", "帅"]console.log(newArr);//["第"]
暂无说明
判断对象是否有这个属性,返回布尔值。
var obj = { "name":"小乔", "age":33}console.log(obj.hasOwnProperty("name"));//trueconsole.log(obj.hasOwnProperty("sex"));//false
删除一个属性,使用方式 delete 对象.属性名
var obj = { "name":"小乔", "age":33}delete obj.name;console.log(obj);//{age: 33}
取得一个数的绝对值,不改变原数
var a = -33;console.log(Math.abs(a));//33console.log(a);//-33
向上取整,不改变原数
var a = 10.2;console.log(Math.ceil(a));//11console.log(a);//10.2
向下取整,不改变原数
var a = 10.9;console.log(Math.floor(a));//10console.log(a);//10.9
四射五入取整,对原数没有影响,注意这里的是取整,如果需要四舍五入且保留几位小数,需要用toFixed(小数位)方法。
var a = 10.46;console.log(Math.round(a));//10console.log(a);//10.46var b = 10.58console.log(Math.round(b));//11console.log(b);//10.58
求出最大值
console.log(Math.max(10,22,4,101,77));//101
求出最小值
```js
console.log(Math.min(10,22,4,101,77));//4
获取一个0~1的随机数(包括0,不包括1)
```js
console.log(Math.random());//随机输出
用法示例:
获得一个1-9之间的随机数
console.log(Math.ceil(Math.random()*10));//输出0-9之间的随机数
获取一个随机颜色(含透明度)
var r = Math.floor(Math.random()*256);//向下取整,如果要向上取整,就乘以255var g = Math.floor(Math.random()*256);var b = Math.floor(Math.random()*256);//透明度是0-1之间的一个数var alph = Math.random().toFixed(1);console.log("rgb("+r+","+g+","+b+","+alph+")");
圆周率
console.log(Math.PI);//3.141592653589793
获取年份
```js
var date = new Date();
console.log(date.getFullYear());//2019
获取月份,由于从0开始计算,所以实际月份需要+1
var date = new Date();console.log(date.getMonth()+1);//6
获取日
var date = new Date();console.log(date.getDate());//26
获取星期
var date = new Date();console.log(date.getDay());//4
获取时
var date = new Date();console.log(date.getHours());//8
获取分
var date = new Date();console.log(date.getMinutes());//34
获取秒
var date = new Date();console.log(date.getSeconds());//5
获取毫秒
var date = new Date();console.log(date.getMilliseconds());//533
获取完整时间信息
var date = new Date();console.log(date.toLocaleString());//2019/9/27 上午8:45:22console.log(date.toLocaleTimeString());//上午8:46:46console.log(date.toLocaleDateString());//2019/9/27
时间格式函数综合运用:
function getTime(type){ var date = new Date(); var y = date.getFullYear();//年 var m = date.getMonth() + 1;//月 var d = date.getDate();//日 var h = date.getHours();//时 var i = date.getMinutes();//分 var s = date.getSeconds();//秒 //格式设置 m = m > 10 ? m : "0" + m; d = d > 10 ? d : "0" + d; h = h > 10 ? h : "0" + h; i = i > 10 ? i : "0" + i; s = s > 10 ? i : "0" + s; //判断传入参数类型 if(!isNaN(type)){ if(type == 0){ return (y+"/"+m+"/"+d+" "+h+":"+i+":"+s); }else if(type == 1){ return (y+"/"+m+"/"+d); }else if(type == 2){ return (h+":"+i+":"+s); }else{ return ("0 完整日期和时间; 1 获取日期; 2 获取时间;"); } }else{ return ("0 完整日期和时间; 1 获取日期; 2 获取时间;") }}console.log(getTime(0));//2019/09/27 09:30:30console.log(getTime(1));//2019/09/27console.log(getTime(2));//09:30:30console.log(getTime(7));//0 完整日期和时间; 1 获取日期; 2 获取时间;console.log(getTime("你好"));//0 完整日期和时间; 1 获取日期; 2 获取时间;
设置时间对象
var stime = "2019/09/27";var date = new Date(stime);console.log(date.getFullYear());//2019 返回number类型
设置包含时分秒的时间对象
var stime = "2019-09-27T02:06:04";var date = new Date(stime);console.log(date.getFullYear());//2019 返回Number类型console.log(date.getSeconds());//4 返回Number类型
var time1 = "2019-09-25T10:30:10";var time2 = "2019-09-27T15:30:20";var t1 = new Date(time1);var t2 = new Date(time2);console.log(t1.getTime());//1569378610000 获得毫秒数console.log(t2.getTime());//1569569420000 获得毫秒数var chazhi = t2.getTime() - t1.getTime();//计算差值//毫秒数转化成秒chazhi = chazhi/1000;//天2.208449074074074,取整得到天var tian = parseInt(chazhi/(24*60*60));console.log(tian+"天");//2天//小时5.002777777777778,取整得到小时var xiaoshi = parseInt((chazhi - (tian*24*60*60))/3600);console.log(xiaoshi+"小时");//5小时//分钟0.16666666666666666,取整得到分钟var fen =parseInt( (chazhi - ((tian*24*60*60)+(xiaoshi*60*60)))/60);console.log(fen+"分钟");//0分钟var miao = chazhi - ((tian*24*60*60)+(xiaoshi*60*60));console.log(miao+"秒");//10秒
一次性定时器
setTimeout(function(){ console.log("你好");},3000)//延迟三秒,输出你好
周期性定时器
setInterval(function(){ console.log("你好");},3000)//每隔三秒,输出你好
setInterval(function(){ var date = new Date(); console.log("现在时间:"+date.toLocaleTimeString());},1000)//每隔1秒,输出 现在时间:下午1:19:15 现在时间:下午1:19:16 ...
由于可能网页内有多个定时器,所以一般都用一个变量来接受一个定时器,每个变量都返回一个编号。
var time1 = setTimeout(function(){ console.log( "我是第1个一次性定时器");},1000)console.log(time1);//1var time2 = setTimeout(function(){ console.log( "我是第2个一次性定时器");},1000)console.log(time2);//2
清除一次性定时器
var time1 = setTimeout(function(){ console.log( "我是第1个一次性定时器");},1000)var time2 = setTimeout(function(){ console.log( "我是第2个一次性定时器");},1000)clearTimeout(1);//等价于clearTimeout(time1),第一个不执行了,第二个执行了一次
清除周期性定时器
var time1 = setInterval(function() { console.log("我是第1个周期性定时器") }, 1000)var time2 = setInterval(function() { console.log("我是第2个周期性定时器") }, 1000)clearInterval(1);//等价于clearInterval(time1),第一个不执行了,第二个每隔1秒执行一次
var 变量 = new RegExp("文字模式","修饰符");
修饰符 i 忽略大小写 g 全文匹配 m 多行匹配
var str = "abcaswfkjlsfdjsa";var par = new RegExp("z");//正则.test(字符串);返回布尔值var res = par.test(str);console.log(res);//falsevar par2 = new RegExp("W","i");var res2 = par2.test(str);console.log(res2);//true,启用了忽略大小写修饰符var ok = par2.exec(str);console.log(ok);//返回正则匹配到的信息,没有匹配到返回nullconsole.log("出现的位置是:"+ok["index"]);//5,注意,找到第一次即返回,不会全部查找。
var 变量 = /文字模式/修饰符
var str = "大家好才是真的好a";var rex = /真/;console.log(rex.test(str));//true
返回匹配到的信息,没有匹配到返回null,同正则匹配同内容多次的话,后面的一次检索是从上一次检索到的位置后开始的。
var str = "just do it";var par = /t/g;//全局匹配var index = 0; //累计找到的次数do{ var result = par.exec(str); if(result != null){ console.log("次数:"+(++index)+","+"找到的下标位置是:"+result["index"]); }}while(result != null);
以上代码输出内容:
次数:1,找到的下标位置是:3
次数:2,找到的下标位置是:9
比exec方便,使用的时候需要开启全局g修饰符
var str = "as;df 3!e[R e7";var pre = /\w/g;console.log(str.match(pre));//返回所有字符(数字+字母)的一个Array结果
\w 单词字符(字母+数字)
var str = "as;df 3!e[R e7";var pre = /\w/g;console.log(str.match(pre));//返回所有字符(数字+字母)的一个Array结果
\W 非单词字符
var str = "as;df 3!e[R e7";var pre = /\W/g;console.log(str.match(pre));//返回所有字符(非数字字母)的一个Array结果
\d 数字
var str = "as;df 3!e[R e7";var pre = /\W/g;console.log(str.match(pre));//["3","7"]Array形式
\D 非数字
var str = "as;df 3!e[R e7";var pre = /\D/g;console.log(str.match(pre));//除数字外的Array形式
\s 空白字符(空格)
var str = "as;df 3!e[R e7";var pre = /\s/g;console.log(str.match(pre));//[" ", " "]
\S 非空字符
var str = "as;df 3!e[R e7";var pre = /\S/g;console.log(str.match(pre));//返回除空白的一个Array
\n 换行符
var str = "as;d\nf 3!e[R e7";var pre = /\n/g;console.log(str.match(pre));//["?"]
\f 换页符
var str = "as;d\nf 3!\fe[R e\f7";var pre = /\n/g;console.log(str.match(pre));//["", ""]两个
\r 回车符
\t 制表符
. 查找单个字符,除了换行和行结束符
用于查找某个范围内的字符
var str = "1t 2y3a hjks?d;qAq[年 p";var pre = /[tya]/g;console.log(str.match(pre));//["t", "y", "a"]
var str = "1t 2y3a hjks?d;qAq[年 p";var pre = /[a-k]/g;//a至k范围内存在的console.log(str.match(pre));//["a", "h", "j", "k", "d"]
var str = "1t 2y3a hjks?d;qAq[年 p";var pre = /[0-9]/g;console.log(str.match(pre));//?["1", "2", "3"]
var str = "1t 2y3a hjks?d;qAq[年 p";var pre = /[^atk]/g;console.log(str.match(pre));//返回除atk以外的所有
用于查找指定选项,注意不再是个体,而是按照一个整体去查找
var str = "1t 2y3a hjks?d;qAq[年 p";var pre = /(jk|Aq|Ks)/g;//|表示或者console.log(str.match(pre));//["jk", "Aq"]前两个有,Ks因为字符串只有小写k,所以不匹配
n+ 匹配任何至少包含一个n的字符串
var str = "1t 2y3a hjks?d;qAqq[年 p";var pre = /q+/g;console.log(str.match(pre));//["q", "qq"]
n* 匹配任何包含0个或者多个n的字符串
var str = "1t 2y3a hjks?d;qAqq[年 p";var pre = /qq*/g;//q可以为0个(所以找到了q,q也可以为多个,所以找到了qq,所以n*前面一般会多一个或多个限定字符,这里多了一个q)console.log(str.match(pre));//["q", "qq"]
n? 匹配任何包含0个或者一个n的字符串
var str = "1t 2y3a hqqqjks?d;qAqq[年 p";var pre = /qq?/g;//q可以为1个(所以找到了qq,q也可以为0个,所以找到了三q里的最后一个q,然后有找到单独的一个q,最后找到结尾的qq)console.log(str.match(pre));//["qq", "q", "q", "qq"]
n{X} 匹配包含x个n的序列的字符串。
var str = "1t 2y3a hqqqjks?d;qAqq[年 p";var pre = /q{3}/g;//匹配3个qconsole.log(str.match(pre));//["qqq"]
n{X,Y} 匹配X个~Y个的序列字符串
var str = "1t 2y3a hqqqjks?d;qAqqqq[年 p";var pre = /q{1,3}/g;//匹配1个~3个的字符串(1个,2个,3个)```console.log(str.match(pre));//["qqq", "q", "qqq", "q"]
n{X,} 匹配至少x个的序列字符串
var str = "1t 2y3a hqqqjks?d;qAqqqq[年 p";var pre = /q{2,}/g;console.log(str.match(pre));//["qqq", "qqqq"]
**n\(** 匹配任何结尾为n的字符串 ```js var str = "1t 2y3ap hqqqjks?d;qAqqqq[年 ta"; var pre = /ta\)/g;//要看整个字符串结尾是否是ta结尾
console.log(str.match(pre));//["ta"]
**^n** 匹配任何以n为开头的字符串
js
var str = "1t 2y3ap hqqqjks?d;qAqqqq[年 ta";
var pre = /^1t/g;//要看整个字符串是否是1t开头
console.log(str.match(pre));//["1t"]
**?=n** 匹配任何其后紧跟n的字符串,记住这个一般要用括号括起来代表一组,不然会报错.
js
var str = "1t 2y3ap hqqqjks?d;qAqqqq[年 ta";
var pre = /(?=a)/ig;
console.log(str.match(pre));//["", "", ""]3处紧跟a(不区分大小写)
**?!n** 匹配任何其后没有紧接指定字符串n的字符串
js
var str = "1t 2y3ap ahqajks?d;qAq[年 ta";
var pre = /a(?!p)/ig;
console.log(str.match(pre));//["a", "a", "A", "a"]
```
手机号验证 ^1[3-9]\d{9}$
数字1开头^1,随后为3~9的任意9位数字[3-9]\d{9},最后1位以数字结尾$
var pre = /^1[3-9]\d{9}$/;console.log(pre.test("13852920087"));//trueconsole.log(pre.test("12852920087"));//falseconsole.log(pre.test("1385292008"));//false
正数正则 ^\d.?\d+$
数字开头^\d,匹配0个或者多个,同时正数也包含小数点且小数点只能为1个或0个.?(.前面的符号为转义) 小数点后至少要出现1次数字\d+ 最后按照数字结尾$
var pre = /^\d*\.?\d+$/;console.log(pre.test("4"));//true;console.log(pre.test("4.67"));//true;console.log(pre.test("0.114"));//true;console.log(pre.test("-3"));//false;
负数正则 ^-\d*.?\d+$
var pre = /^-\d*\.?\d+$/;console.log(pre.test("4"));//falseconsole.log(pre.test("-4.67"));//true;
数字正则 ^-?\d*.?\d+$
var pre = /^-?\d*\.?\d+$/;console.log(pre.test("4"));//falseconsole.log(pre.test("-4.67"));//true;console.log(pre.test("ad"));
整数正则 ^-?\d+$
var pre = /^-?\d+$/;console.log(pre.test("4"));//trueconsole.log(pre.test("-4"));//trueconsole.log(pre.test("-4.1"));//falseconsole.log(pre.test("4.1"));//false
邮箱正则 ^([A-Za-z0-9_-.])+@([A-Za-z0-9_-.])+.([A-z]{2,4})$
var pre = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-z]{2,4})$/;console.log(pre.test("wdf@qq.com"));//trueconsole.log(pre.test("df-ad_77@df.com.cn"));//true
如何定义,三种形式
声明方式:
function fn1(){ //函数体}
字面量方式
var fn2 = function(){ //函数体}
new关键字
var fn3 = new Function(/*函数体*/);
全局变量是window的属性
var str = "小鸡炖蘑菇";console.log(window.str);//小鸡炖蘑(str全局变量是整个window的一个属性)
声明方式定义的函数是window的方法
function atr(){ console.log("很帅");}console.log(window);//可以看到控制台window包含的对象方法中含有atr方法
全局的this指向的就是window对象(全局)
console.log(this);
函数的this指向的是window对象(全局)
function say(){ console.log(this);}say();
其实上面的例子等价于:
var say = function(){ console.log(this);}window.say();//所以说函数的this指向的也是window对象
对象内部的this
var wuge = { name:"武哥", msg:function(){ console.log("wuge的msg方法");//wuge的msg方法 console.log(this);//{name: "武哥", msg: ?} }}wuge.msg();
this指向的是当前运行的上下文对象,也可以理解为指向当前所在函数归属的对象,在上面的例子中,this隶属于匿名函数function,而function归msg,msg归wuge,所以this指向的是wuge,来看综合的例子
var tacher = { name:"武哥", run: function(){ console.log(this);//指向tacher //字面量方式定义一个函数 var tt = function(){ console.log(this);//指向的是window } //声明方式定义一个函数 function bb(){ console.log(this);//指向的也是window } bb(); tt(); }}tacher.run();
注意:只要是字面量方式或者声明方式定义的函数,其里面的this都是指向全局window,继续例子:
function gogo(){ console.log(this); //指向window function yy(){ console.log(this); //window } yy(); var mm = function(){ console.log(this); //window } mm(); var obj = {name:"小乔"}; obj.mm = mm; obj.mm(); //此时this指向obj}gogo();
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题。
例子1:
function a(){ var user = "追梦子"; console.log(this.user); //undefined console.log(this); //Window}a();
按照我们上面说的this最终指向的是调用它的对象,这里的函数a实际是被Window对象所点出来的,下面的代码就可以证明。
function a(){ var user = "追梦子"; console.log(this.user); //undefined console.log(this); //Window}window.a();
和上面代码一样吧,其实alert也是window的一个属性,也是window点出来的。
例子2:
var o = { user:"追梦子", fn:function(){ console.log(this.user); //追梦子 }}o.fn();
这里的this指向的是对象o,因为你调用这个fn是通过o.fn()执行的,那自然指向就是对象o,这里再次强调一点,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个。
其实例子1和例子2说的并不够准确,下面这个例子就可以推翻上面的理论。
如果要彻底的搞懂this必须看接下来的几个例子。
例子3
var o = { user:"追梦子", fn:function(){ console.log(this.user); //追梦子 }}window.o.fn();
这段代码和上面的那段代码几乎是一样的,但是这里的this为什么不是指向window,如果按照上面的理论,最终this指向的是调用它的对象,这里先说个而外话,window是js中的全局对象,我们创建的变量实际上是给window添加属性,所以这里可以用window点o对象。
这里先不解释为什么上面的那段代码this为什么没有指向window,我们再来看一段代码。
var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //12 } }}o.b.fn();
这里同样也是对象o点出来的,但是同样this并没有执行它,那你肯定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不准确,接下来我将补充一句话,我相信你就可以彻底的理解this的指向的问题。
情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。
情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,例子3可以证明,如果不相信,那么接下来我们继续看几个例子。
var o = { a:10, b:{ // a:12, fn:function(){ console.log(this.a); //undefined } }}o.b.fn();
尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。
还有一种比较特殊的情况,例子4:
var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //undefined console.log(this); //window } }}var j = o.b.fn;j();
这里this指向的是window,是不是有些蒙了?其实是因为你没有理解一句话,这句话同样至关重要。
this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window,这和例子3是不一样的,例子3是直接执行了fn。
this讲来讲去其实就是那么一回事,只不过在不同的情况下指向的会有些不同,上面的总结每个地方都有些小错误,也不能说是错误,而是在不同环境下情况就会有不同,所以我也没有办法一次解释清楚,只能你慢慢地的去体会。
构造函数版this:
function Fn(){ this.user = "追梦子";}var a = new Fn();console.log(a.user); //追梦子
这里之所以对象a可以点出函数Fn里面的user是因为new关键字可以改变this的指向,将这个this指向对象a,为什么我说a是对象,因为用了new关键字就是创建一个对象实例,理解这句话可以想想我们的例子3,我们这里用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a,那么为什么对象a中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。
除了上面的这些以外,我们还可以自行改变this的指向,关于自行改变this的指向请看JavaScript中call,apply,bind方法的总结这篇文章,详细的说明了我们如何手动更改this的指向。
更新一个小问题当this碰到return时
function fn() { this.user = '追梦子'; return {}; }var a = new fn; console.log(a.user); //undefined
再看一个
function fn() { this.user = '追梦子'; return function(){};}var a = new fn; console.log(a.user); //undefined
再来
function fn() { this.user = '追梦子'; return 1;}var a = new fn; console.log(a.user); //追梦子
继续来
function fn() { this.user = '追梦子'; return undefined;}var a = new fn; console.log(a.user); //追梦子
什么意思呢?
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。
function fn() { this.user = '追梦子'; return undefined;}var a = new fn; console.log(a); //fn {user: "追梦子"}
还有一点就是虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。
function fn() { this.user = '追梦子'; return null;}var a = new fn; console.log(a.user); //追梦子
知识点补充:
1.在严格版中的默认的this不再是window,而是undefined。
2.new操作符会改变函数this的指向问题,虽然我们上面讲解过了,但是并没有深入的讨论这个问题,网上也很少说,所以在这里有必要说一下。
function fn(){ this.num = 1;}var a = new fn();console.log(a.num); //1
为什么this会指向a?首先new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。
注意: 当你new一个空对象的时候,js内部的实现并不一定是用的apply方法来改变this指向的,这里我只是打个比方而已.
if (this === 动态的\可改变的) return true;
var fn = function(x1,x2,x3){ console.log(fn.arguments); //实参的个数(2) console.log("fn"); } fn(10,20); console.log(fn.name);//函数的名称 console.log(fn.length);//形参的个数(3)
改变this的指向
function tt(x1,x2){ console.log(x1,x2); console.log(this);}var zhangsan = { name:"张三", say:function(){ console.log(this); }}tt(11,22);//输出11,22,然后console.log(this)指向的是全局windowtt.call(zhangsan,44,55);//输出44,55,tt这个函数call了zhangsan,那么就是zhangsan去调用tt,此时this就指向的是zhangsan对象
和上面一样,改变this指向
function tt(x1,x2){ console.log(x1,x2); console.log(this); } var zhangsan = { name:"张三", say:function(){ console.log(this); } } tt(11,22);//输出11,22,然后console.log(this)指向的是全局window tt.apply(zhangsan,[44,55]);//输出44,55,tt这个函数apply了zhangsan,那么就是zhangsan去调用tt,此时this就指向的是zhangsan对象
和上面一样,改变this指向
function tt(x1,x2){ console.log(x1,x2); console.log(this);}var zhangsan = { name:"张三", say:function(){ console.log(this); }}tt(11,22);//输出11,22,然后console.log(this)指向的是全局windowtt.bind(zhangsan)(44,55);//输出44,55,tt这个函数bind了zhangsan,那么就是zhangsan去调用tt,此时this就指向的是zhangsan对象
综合实例:通过改变this的指向,可以实现不同对象之间方法的相互借用,调用。
var stu1 = { name:"刘备", say:function(){ console.log("say方法"); console.log(this.name+"执行了say方法"); console.log(this); } } var stu2 = { name:"关羽", run:function(){ console.log("run方法"); console.log(this.name+"执行了run方法"); console.log(this); } } //stu1(刘备)要用stu2(关羽)的run stu2.run.call(stu1); //关羽要用刘备的say stu1.say.call(stu2);
函数名相同,参数或者参数的类型不同,从而实现不同的目的,比如同样一个函数,传入一个参数就执行console.log,传入两个参数就实现加法等等。
实现方法:一、使用 arguments.length
function test(){ switch(arguments.length){ case 0: console.log("没有传入参数"); break; case 1: console.log("传入了一个参数"); break; case 2: console.log(arguments[0] + arguments[1]); }}test();//没有传入参数test(1);//传入了一个参数test(1,1);//2