JS学习的第三周

138 阅读16分钟

一.字符串的API★★★★★

转义字符:\

在字符串之中出现了和程序冲突的字符时使用

比如:希望在双引号之中在放入一个双引号,在单引号中放入单引号

"\""   '\''
特殊功能的转义字符

\n 换行

\t 制表符:相当于tab出来的大空格

可以书写unicode号代表的字

\uXXXX 输出某一个字

汉字的第一个字:\u4e00

汉字的最够一个字:\ u9fa5

★英文转大小写:

统一的将字符串转为大写或者小写,再比较,忽略大小写(验证码)

大写 var upper=str.toUpperCase();

小写 var lower=str.toLowerCase();

获取字符串中的某一个字符:

str.CodeAt(); === str[i];

获取字符串中的每一个字符的ASCII码:

var ascii=str.charCodeAt(i);

通过ASCII码转回原文:

var tex=String.fromcharCode();

::selection{background:transparent;}设置文字双击后的选择颜色

检索字符串:检查索引/下标

使用:判断有没有,不重复

var i = str.indexOf("关键字",start i);

特殊:

1.start i可以省略

如果省略默认从0位置开始向右查找

2.返回

如果找到了,返回关键字的第一个字符的下标

★★★没找到返回-1,重点:我们不关系下标为多少,只关心下标是不是-1,为-1就是说明没有,如果不为-1,说明存在

3.数组也可以使用

其实以前的数组没有这个方法,某浏览器更新后,数组才可以使用(老IE浏览器(ie8一下的)用不到)

4.笔试题

知道所有关键字的下标

var str="no zuo no dai no can no bb";
var index=-1;
while((index=str.indexOf("no",index+1))!=-1){
    console.log("下标为"+index);
}p

5.拼接字符串

var newStr=str.concat(str1,str2.....);还不如 + 连接字符串

6.★截取字符串:3种

★1. var subStr=str/arr.slice(start i,end i+1);

2.var subStr=str.subString(start i,end i+1); 几乎和slice一致,但是不如slice,因为不支持负数的参数

★3. var subStr=str.substr(start i,n) 截取的个数,不必考虑含头不含尾

7.★替换字符串

var newStr=str.replace("固定关键字"/RegExo,"新内容");

这个方法很厉害,目前没学过正则表达式,所以替换暂时只能替换一个固定关键字,比较low

8.★★★★★切割/分隔字符串:功能:字符串<=>数组

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]

一个汉字[\u4eoo-\u8fa5]

除了xxx之外,其他都可以

                [^xxx]-范围广,不推荐

预定义字符集:前辈们提前定义了一些常用的字符集

一个数字:\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-Za-z]{4,6}$/  只能输入一个数字和大写字母组成的4-6位密码

★★★★★字符串支持正则的API

切割

var a = string.split("固定切割符")

替换

基础替换:var a = string.replace(“关键字”,"新值")

★★ 
var str="卧槽,我操,我草,握草,卧草,我曹,窝草,窝槽,我去操"
str.replace(/[我卧握窝][草曹操]+/g,"**")

高级替换:

str=str.replace(/[我卧握窝][去槽操曹草]+/g,function(key,i,str){//此回调函数会自动调用,找到几个关键字就会执行几次
//              console.log(key);//当前次正则匹配到的关键字
//              console.log(i);//当前次正则匹配到的关键字的下标
//              console.log(str);//原文本身
                return key.length==2?"**":"***";
            });

格式化

如果替换式,正则中,带有分组,那么你的回调函数会由更多的形参

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.onsubmit=function(){}

Math:专门用于提供数学计算的API

强调:不能,不需要创建,浏览器自带的

属性:Math.PI

API:

向上取整:Math.ceil()

向下取整:Math.floor()

四舍五入:Math.round()

固定精度:Math.toFixed() 缺点:返回的是字符串 用parseFloat包起来

固定长度:Math.toPrecision()

取整:Math.parseInt()、位运算

乘方,开方

*乘方:Math.pow(底数,幂)

开放:math.sqrt()

最大值,最小值

Math.max()

Math.min()

缺陷:不支持传入数组参数,不能比较数组的最大值和最小值

解决:Math.max/min.apply(Math,arr);

apply可以悄悄打散数组,将每一个元素单独传入--ES5带来的特性

apply可以借用方法

笔试题:比较出数组中的最大值和最小值(2 种方法) for循环遍历比较,Math.max.apply(Math,arr)

绝对值:

Math.abs();

随机数:

parseInt(Math.randow()*(max-min+1)+min);随机整数

Math.random(); 默认0-1之间取随机数

可以取到0,但不可能取到1

在min和max之间取随机数

parseInt(Math.random()*(101)); 可以取最大值

parseInt(Math.random()*(100)+1); 可以取最小值以及最大值

笔试题:

封装自定义函数,按照任意小数位四舍五入,返回数字类型

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=11=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对象

1.浏览器自带4中错误类型,可以快速找到错误

 EvalError(eval错误)
3 RangeError(范围错误)
4 ReferenceError(引用错误)
5 SyntaxError(语法错误)
6 TypeError(类型错误)
7 URIError(URI错误)

SyntaeError——语法错误:符号或者语法错了

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.onresize=function(){
    return inner();
}
function fdjl(){
            var timer;
            return function () {
                if (timer) {
                    clearTimeout(timer);
                }
         timer=setTimeout(function(){
             函数体;(需要做的操作)
         },时间)
        }
    }
}
var inner=fdjl();//inner()内层函数才是写在事件中的操作

Object面向对象开发方式

三大特点:封装,继承,多态

面试题:简单说一下你了解的面向过程和面向对象 开发方式的区别?

面向过程:开始--经过--结束,从一开始学习到学习写法都是面向过程

面向对象:对象(属性和方法),如果这个世界有各种属性和各种方法,但是练一个对象/生物都没有,那些对象就没有具体意义

创建自定义对象:

1.直接量方式:

var obj={
    "属性名1":属性值1, 
    "属性名2":属性值2, 
    .....
    "方法名":function(形参1...){函数体};
}

1.强调

1.属性名和方法名的引号其实可以省略,但是不建议,因为以后会学到一种数据 JOSN 要求属性名和方法名的双引号不能省略

2.如何访问对象的属性和方法: 对象名.属性名() 对象名.方法名() 对象名["属性名"] 对象名["方法名"] ()

3.特殊:

1.访问到没有创建过的属性,返回undefined

2.随时随地可以添加不存在的属性和方法

3.通过for in 获取对象中的所有属性或者方法

for (var i in 自定义对象名[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...);

\