start i 代表开始位置
end i 代表结束位置
字符串API
英文转大小写
toUpprecase 转大写
toLowerCase 转小写
获取字符串的某一个字符
str.codeAt();
获取字符串字符的ASCII码
str.charCodeAt();
通过ASCII码值转回原文
str.fromcharCodeAt();
补充:CSS ::section{background:transparent;} 页面双击文字会出现蓝色背景的选择效果,该代码把双击选择效果设置成了透明色
检索字符串:检查索引/下标
使用:判断有没有该关键字,不重复
var i = str.indexOf("关键字",strat i);
特殊:
1.start i可以省略,如果省略默认从0位置开始向右查找
2.返回:如果找到了,返回关键字的第一个字符的下标
★★★没找到返回-1,重点:我们不关系下标为多少,只关心下标是不是-1,为-1就是说明没有,如果不为-1,说明存在
3.数组也可以使用:其实以前的数组没有这个方法,某浏览器更新后,数组才可以使用(老IE浏览器(ie8以下的)用不到)
补充:笔试题:
var str="no zuo no dai no can no bb";
var index=-1;
while((index=str.indexOf("no",index+1))!=-1){
console.log("下标为"+index);
}
拼接字符串
var newStr=str.concat(str1,str2.....);还不如 + 连接字符串
截取字符串:三种方式
arr.slice(strat i,end i+1); 开始位置包含,结束位置不包含(含头不含尾)
arr.subString(strat i,end i+1); 几乎和slice用法相同,但是不支持负数
arr.substr(strat i, n); 从开始位置,截取N个数,开始位置和结束的位置都包含 (含头含尾)
这里推荐使用 arr.substr(strat i, n);
替换字符串
str.replace("固定关键字","新内容");
此方法搭配正则就很好
切割/分隔字符串
var arr=str.split("自定义切割符");
特殊:
1.切割符可以自定义,切割后返回的是一个数组,数组中不在包含切割符
2.如果传入的切割符是一个“” 空,每一个字符都会被切
扩展:JS创建页面元素并且渲染上DOM树:3步
1、创建空标签: var 新元素=document.createElement("标签名");
2、为此标签设置必要的属性和事件
新元素.属性名="属性值";
新元素.on事件名=function(){操作}3、把新元素上DOM树
父元素.appendChild(新元素);
正则表达式
正则表达式:定义字符串中出现规则的表达式
使用:做切割/替换/“验证”的时候使用
最简单的正则就是关键字原文,写法和以前的字符串不同 例:“no” --> /no/gi
i:忽略大小写
g:替换所有;替换默认替换第一个匹配的字符
var a = "a b c a d e f a g a";
a.replace(/no/gi,"p");
被选字符集:规定一位字符可能出现的情况
强调:一个中括号只能管理一个值
问题:正则只要满足后,就不在关后续操作,后续用户可以乱输入
解决:做验证,希望用户根据我们的想法来操作;必须写成:/^备选字符集$/ /^表示从开头 /$表示到结尾 表示用户从头到尾都必须完全匹配
特殊:
如果被选字符集unicode号是连续的,就用-省略中间部分
比如: 一个数字[0-9]
一个字母[A-Za-z]
一个数字,字母,下划线[0-9A-Za-z]
一个汉字[\u4e00-\u9fa5]
预定义字符集:
一个数字:\d
一个英文,数字,下划线:\w
一个空白字符: \s
一位除了换行外的所有字符: . (点) 不推荐此字符集
问题:预定义字符集,是固定的,不够灵活
开发时,优先使用预定义字符集,在预定义字符集满足不了时,就使用备选字符集补充
强调:备选字符集和预定义字符集都只能管一位字符
量词规定一个字符集出现的次数
使用:
有明确数量:
字符集{n,m}; 前边相邻的字符集最少出现n次,最多出现m次
字符集{n}; 前边相邻的字符集最少出现n次,不限制最多出现次数
字符集{n}: 前边相邻字符集必须出现n次
没有明确数量:
字符集? 该字符集可有可无,最多一次
字符集* 该字符集可有可无,不限制最多出现次数
字符集+ 至少写一个该字符集,不限制最多出现次数
指定匹配位置
^:以...开头
$:以...结尾
特殊:如果同时使用了 前面^和后面$({/^ $/ } 从头到尾完全匹配
选择和分组
选择:可以在多个条件中,选择一个
规则1|规则2(字符集1|字符集2)
分组:选择和分组一般情况下是搭配使用------添加子规则
(规则1|规则2)
新老身份证的正则
/^(\d{15}|\(d{17}[0-9Xx])&/
预判
目的:密码强度:4-6位密码,可以输入字母数字,但必须有一位大写和以为数字组成
公示:固定搭配
/^(?![0-9]+$)$/ 不能全由数字组成,可能有大写字母,小写字母,汉字,特殊符号,其他语言....
/^(?![0-9]+$)[0-9A-Za-z]{4}$/ 不能全数字,只能输入四位,可以是小写字母大写字母数字之间的组合^(?![A-Za-z]+$)$/ 不能全有英文组成,可能有数字,可能有汉字,可能有特殊符号,其他语言....
/^(?![A-Za-z]+$)(?![0-9a-z]+$)(?![0-9A-Z]+$)[0-9A-Za-z]{4,6}$/ 只能输入由一个大写字母和一个小写字母和一个数字组成的4-6位密码
/^(?![A-Za-z]+$)(?![0-9a-z]+$)[0-9A-Z]{4,6}$/ 只能输入一个数字和大写字母组成的4-6位密码
字符串支持正则的API
切割
var a = string.split("固定切割符")
替换
var a = string.replace(“关键字”,"新值")
格式化
如果替换式,正则中,带有分组,那么你的回调函数会由更多的形参
var str="500103198602215933";
var reg=/\d{6}(\d{4})(\d{2})(\d{2})\d{4}/;
str=str.replace(reg,function(key,a,b,c,i,str){
// console.log(key);//正则匹配到的内容
// console.log(a);//第一个分组匹配到的内容
// console.log(b);//第二个分组匹配到的内容
// console.log(c);//第三个分组匹配到的内容
// //... 你有多少个分组就会多出多少个形参,但是最后两个一定是下标和原文
// console.log(i);
// console.log(str);
return a+"年"+b+"月"+c+"日";
})
console.log(str);
正则对象
创建
直接量方式: var reg=/正则表达式/后缀
构造函数方式: var reg=rew RegExp("正则表达式","后缀")
验证方法: var bool=reg test("用户输入的东西");
true 用户输对了 flase 用户不通过
失去焦点事件onblur
获得焦点事件onfocus
提交事件onsubmit
阻止表单提交form.οnsubmit=function(){}
Math:专门用于提供数学计算的API
强调:不需要创建,浏览器自带的
属性:Math.PI
API:
向上取整:Math.ceil()
向下取整:Math.floor()
四舍五入:Math.round()
固定精度:Math.toFixed() 缺点:返回的是字符串 用parseFloat包起来
固定长度:Math.toPrecision()
取整:Math.parseInt()、位运算
乘方/开方
乘方:Math.pow(底数,幂)
开方:Marh.sqrt()
最小值,最大值
Math.max()
Math.min()
缺陷:不支持传入数组参数,不能比较数组的最大值和最小值
解决:Math.max/min.apply(Math,arr);
apply可以悄悄打散数组,将每一个元素单独传入--ES5带来的特性
apply可以借用方法
笔试题:比较出数组中的最大值和最小值(2 种方法) for循环遍历比较,Math.max.apply(Math,arr)
绝对值,随机数
绝对值Math.abs();
随机数Math.random(); 默认0-1之间取随机数,可以取到0,但不可能取到1
parseInt(Math.randow()*(max-min+1)+min);随机整数
在min和max之间取随机数
parseInt(Math.random()*(101)); 可以取到的最大值100,最小值0
parseInt(Math.random()*(100)+1); 可以取到的最小值1以及最大值100
笔试题:
封装自定义函数,按照任意小数位四舍五入,返回数字类型
function dy(num,d){
num*=Math.pow(10,d);
num=Math.round(num);
num/=Math.pow(10,d);
return num;
}
var res=dy(Math.PI,3);
console.log(res);
Date:封装了一个时间对象提供了对时间进行操作的API的对象
使用:计算和时间相关的,就得用到date对象
创建(4种):
**1.创建一个日期对象,获得客户端的当前时间
var a = new Date();
**2.创建一个自定义时间:
var time = new Date("1986/02/26 12:32:54");
3.创建一个自定义时间:
var time = new Date(yyyy,MM,dd,hh,mm,ss)
取值范围:MM 0~11月 月份需要修正 0=1月 1=2月...11=12月
**4.复制一个日期对象
日期对象的API都是直接修改日期对象的原值,无法获取修改之前的日期
解决:如果希望同时获取修改前和修改后的日期,则应该先把原日期复制一份,再去修改其中的一份日期
var start = new Date("1986/02/26 12:32:54");
var copy = new Date(start);
使用:
1.拿着两个日期对象可以相减,得到一个毫秒差,通过毫秒差换算出你想要的任何一部分
2.日期的API操作:分量:时间单位
年/月/日/星期:Fullyear / Month / Date / day
时/分/秒/毫秒:Hours / Minutes / Seconds / Milliseconds
1.获取方法:
getFullyear / getMonth / getDate
getHours / getMinutes / getSeconds / getMilliseconds
设置方法:
setFullyear / setMonth / setDate
setHours / setMinutes / setSeconds / setMilliseconds特殊:Day(星期):没有set方法
2.取值范围:
Fullyear:就是当前年份的数字
Month:0~11,计算机中的月份比现实-1
date:1~31
day:0~6 0代表星期天
Hours:0~23
Minutes,Seconds:0~59
3.日期对象和字符串能用的API不同,而且日期对象可以自动进制
建议:对一个日期的某个分量做计算
date.setXXXX(date.getXXX() +/- N);
例如:
date.setMinutes(date.getMinutes() + 10); 加十分钟
4.日期格式化
date.toLocaleString();(不推荐) 会转为一个本地日期格式的字符串,不能自动进制,也不能用日期的API,但是可以使用字符串的API
缺点:具有兼容性问题
解决:自定义函数format
Error对象(查询错误)
SyntaxError——语法错误:符号或者语法错了
ReferenceError——引用错误:使用没有创建过的东西
*typeError——类型错误:使用了一个不属于自己的属性或者方法
RangeError——范围错误:只有一个API会遇到,Math.PI.toFiexd(d); d的范围必须在0-100之间
2.错误处理
当程序发生错误时,保证程序不会异常中断的机制
程序默认遇见错误就会停止后续代码的执行,用户体验差
处理:
try{
console.log(Math.PI.toFiexd(-1)); //取值范围错误
}catch(err){
console.log(err); //输出错误信息,建议自己加上中文错误描述
alert("XXXXXXX")
}
可以用if...else....代替try....catch....
if....else....错误提示可以用:
1. throw new Error("XXX");
2. console.log("XXX")
点击获取页面X轴坐标 xxx.clientX;
Function对象
JS中函数就是对象,函数名其实就是引用函数对象的变量
1.创建:三种
声明方式:function 函数名(形参1,形参2....){函数体;return 返回值;} 完整的声明提前
直接量方式: var 函数名=function(){函数体;return 返回值;}声明提前
构造函数方式:var 函数名=new Function("形参1","....","函数体;return 返回值;"); 无论参数什么类型,创建函数的时候都必须用双引号包起来(函数体不是固定的,而是字符串动态拼接的时候使用)
2.★★★重载(overload)
相同函数名,根据传入的实参不同,会自动选择对应的函数执行
问题:JS的语法不支持重载!JS不允许同时存在多个同名函数,如果同时存在,那最后一个函数值会覆盖前面的函数值
解决:函数内部对象:arguments
arguments函数内部自带的,不需要创建,类数组对象,作用:接受所有的实参
类数组对象(类似数组):
可以用下标访问某个元素;可以用length获取长度;可以遍历拿到元素,但不等于数组,不支持数组所有的AIP
何时使用:1.以后不需要形参,也接住所有的实参
2.变相实现重载:
3.★★★匿名函数
创建的函数,没有函数名引用
何时使用:如果函数只会执行一次的时候使用; 为了节约内存,匿名函数没有变量引用,用完就自动释放
如何使用
1.匿名函数自调:
(function(){函数体;}) ( )
★2.匿名函数回调:函数调用时,调入的实参,又是一个匿名函数,不需要我们去调用,主函数会自动执行
arr.sort(function(a,b){return a-b;}) str.replace(reg.function(){})
匿名函数只要不是自调,就是回调:
以后搭配上ES6的箭头函数:简化了一切回调函数
闭包(重要)
1.作用域(scope)
全局作用域
随处都可以用,可以反复使用,但是很容易被污染(被改变)
函数作用域
不会被污染,但是只有函数调用时内部可用,调用结束后会释放,不可以反复使用,每一次使用都是重新开始
函数的执行原理
一.程序加载时
创建执行环境栈(ECS):保存函数调用顺序的数组
首先压入全局执行环境(全局EC)
全局EC中引用着全局对象window
window中保存着全局变量
二.定义时
创建函数对象:封装函数段
在函数对象中定义scope属性,记录着函数来自的作用域
全局函数的scope都是window
三.调用前
在执行环境ECS压入新的函数EC
创建出活动对象(AO):保存本次函数调用用到的局部变量
在EC中添加一个scope chain (作用域链)属性引用着AO
设置AO的parent属性为函数的scope引用的对象
四.调用时
变量的使用规则:有些使用局部变量,没有局部变量就找全局变量,没有全局变量,就会报错
五.调用完
函数的EC会出栈,AO自动释放,局部变量也会自动释放
★★★★★包:保护一个可以[反复使用的局部变量]的一种此法结构
为什么:全局变量:缺:容易被污染
局部变量:缺: 一次性
如何使用:
1、两个函数进行嵌套
2、外层函数创建受保护的局部变量,并且返回内层函数
3、内层函数在操作受保护的局部变量
强调:
1、判断闭包,有没有两个函数在嵌套,并且外层函数创建了变量,return 了内层函数
2、外层函数调用几次,就创建了几个闭包,受保护的变量就有了几个副本
3、同-次外层函数调用,返回的内层函数,都哦是使用同一个受保护的变量
缺点:唯-的缺点:受保护的变量永远不会被释放,过度使用闭包,会导致内存泄漏
使用场景:防抖节流:减少DOM树的修改,提升性能- 3个事件会非常的影响性能,性能差、
1、elem.onmousemove 鼠标移动就会触发,触发次数很多很快,但是不要让他疯狂的渲染DOM
2、window.onresize 窗口的尺寸积要发生变化就会触发,触发次数很多很快,但是不要让他疯狂的渲染DOM
3.input.oninput input框输入的内容发生变化,就会触发
防抖节流
window.οnresize=function(){
return inner();
}
function fdjl(){
var timer;
return function(){
if(timer){clearTimerout(timer)}
timer=setTimeout(function(){
函数体;(需要做的操作)
})
}
}
var inner=fdjl();//inner()内层函数才是写在事件中的操作
Object面向对象开发方式
三大特点:封装,继承,多态
面试题:简单说一下你了解的面向过程和面向对象 开发方式的区别?
面向过程:开始--经过--结束,从一开始学习到学习写法都是面向过程
面向对象:对象(属性和方法),如果这个世界有各种属性和各种方法,但是练一个对象/生物都没有,那些对象就没有具体意义
创建自定义对象:
1.直接量方式:
var obj={ "属性名1":属性值1, "属性名2":属性值2, ..... "方法名":function(形参1...){函数体}; }
例子:轮播的对象封装
HTML部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="lunbo" class="banner">
<img class="active" src="./images/banner.jpg" alt="">
<img src="./images/banner02.jpg" alt="">
<img src="./images/banner03.jpg" alt="">
<img src="./images/banner04.jpg" alt="">
<button><</button>
<button>></button>
<ul>
<li xb="0" class="active"></li>
<li xb="1"></li>
<li xb="2"></li>
<li xb="3"></li>
</ul>
</div>
</body>
</html>
CSS部分
* {
margin: 0;
padding: 0;
}
div {
width: 100%;
height: 500px;
position: relative;
}
div>img {
width: 100%;
height: 100%;
position: absolute;
opacity: 0;
transition: 1s;
}
div>img.active {
opacity: 1;
}
div>button {
width: 50px;
height: 50px;
position: absolute;
top: 50%;
margin-top: -25px;
border-radius: 50%;
border: 1px solid red;
cursor: pointer;
}
div>button:hover{
background: rgba(0, 0, 0, 0.3);
}
div>button:active{
background: rgba(0, 0, 0, 0.7);
}
div>button:nth-of-type(1) {
left: 0;
}
div>button:nth-of-type(2) {
right: 0;
}
ul{
position: absolute;
z-index: 2;
top: 90%;
left: 50%;
margin-left: 10px;
}
ul>li{
width: 20px;
height: 20px;
border-radius: 50%;
display: inline-block;
background: gray;
cursor: pointer;
}
ul>li.active{
background: skyblue;
}
JavaScript部分
var obj ={
btns : document.getElementsByTagName("button"),
lis : document.getElementsByTagName("li"),
imgs : document.getElementsByTagName("img"),
carous : document.getElementById("lunbo"),
j : 0,
timer:null,
init:function(){// 初始化
this.bind();
this.kqdsq();
},
bind:function(){ // 绑定事件
var me= this;
for(var i=0;i<this.btns.length;i++){
this.btns[i].onclick=function(){
if(this.innerText==">"){
me.animate(1);
}else{
me.animate(-1);
}
}
}
for(var i=0;i<this.lis.length;i++){
this.lis[i].onclick=function(){
me.animate(0,this);
}
}
this.carous.onmouseover=function(){
me.tzdsq()
}
this.carous.onmouseout=function(){
me.kqdsq()
}
},
animate : function(num,b){ // 操作
this.clear();
if(num){
this.j+=num;
if(this.j==this.lis.length){
this.j=0;
}else if(this.j==-1){
this.j=this.lis.length-1;
}
}else{
this.j =parseInt(b.getAttribute("xb"));
}
this.lis[this.j].className="active";
this.imgs[this.j].className="active";
},
clear:function(){ // 清除样式
for(var i =0 ;i<this.lis.length;i++){
this.lis[this.j].className="";
this.imgs[this.j].className="";
}
},
kqdsq:function(){
var me=this;
this.timer=setInterval(function(){
me.animate(1)
},2000)
},
tzdsq:function(){
clearInterval(this.timer)
}
}
obj.init();
1.强调: 1.属性名和方法名的引号其实可以省略,但是不建议,因为以后会学到一种数据 JOSN 要求属性名和方法名的双引号不能省略
2.如何访问对象的属性和方法: 对象名.属性名() 对象名.方法名() 对象名["属性名"] 对象名["方法名"] ()
2.特殊:1.访问到没有创建过的属性,返回undefined
2.随时随地可以添加不存在的属性和方法
3.通过for in 获取对象中的所有属性或者方法
for (var i in 自定义对象名){ console.log(i)//拿到下标名称 console.log(自定义对象名[i])//遍历取里面的值 }
4.如果你希望在对象的方法内部使用对象自己的属性,我们需要写为this.属性
this指向: 单个元素绑定事件this---这个元素
多个元素绑定事件this---当前元素
★★函数中的this---谁在调用此函数this就指向谁
定时器中的this--- 指向window
箭头函数this---指向外部对象
自定义构造函数中的this---指向当前创建的对象
2.构造函数方式: 不好用
创建: var obj=new object();
obj.属性名=属性值;
obj.方法名=function(){};
直接量方式和构造函数方式都只能创建单个对象
3.自定义构造函数方式:专门用于创建多个对象
创建:
function 类名(形参1,形参2,形参3....){
this.属性名1=属性值1; //属性名就是形参的名字
this.属性名2=属性值2; this.属性名3=属性值3;
}
调用:
var obj=new 类名(实参1,实参2,实参3...);