day14
事件取消绑定
1.如果使用的 elem.on事件名=()=>{} ,那么写成 elem.on事件名=null ,就可以取消绑定
2.如果使用的 elem.addEventListener("事件名",callback) 那么写成elem.removeEventListener("事件名",callback)
this的指向
1.单个元素绑定事件this ---> 这个元素
2.多个元素绑定事件this ---> 当前元素
3.箭头函数中this ---> 外部对象
4.函数中的this ---> 当前正在调用函数的这个对象
5.定时器中的this ---> window
ES5强制改变this的指向 笔试面试
call/apply:临时的替换了函数中的this --借用
语法:
函数名.call(借用的对象,实参...)- 单独传入每个实参
函数名.apply(借用的对象,arr)-只能传入一个实参 要求必须是一个数组 apply具有打散数组的功能
强调:
call/apply相当于立刻调用函数,立即执行的
bind:永久的替换了函数中的this
三件事
创建了一个和原函数功能完全相同的新函数
将新函数的this永久绑定为了指定对象,无法再次被call/apply
将新函数的部分参数永久固定
语法
var 新函数名 = 函数名.bind(永久对象,永久实参)不是立刻执行,需要调用
三个固定套路
最大值、最小值
Math.max/min/apply(Math,arr) ==> Math.max/min(...arr)
判断是不是数组
Object.prototype.toString.call/apply(arr) == "[object Array]"
类数组转为普通数组
var arr = Array.prototype.slice.call/apply(类数组对象)
var arr = Array.from(类数组对象)
ES6
let const 箭头函数
模板字符串直接识别变量,不再需要+运算符进行拼接,实现了一个简单的js环境,甚至支持在里面做运算写API
`你的名字叫${name}`
解构赋值
解析结构再进行赋值,赋值的新方式,并且得到了增强,如果赋值符号左右两边的结构一样,就会悄悄打开结构再一一赋值
语法
类似数组的解构赋值
let[a,b,c]=[1,2,3]
类似对象的解构赋值
let {a,b="默认值",c}={c:1,a:2,b:3}
调用函数,传递实参的顺序其实无所谓
function zwjs ({name="1",age,hobby})}{
return`我的名字叫${name},今年${age},喜欢${hobby}`
}
zwjs({age:18,hobby:"js"})
函数的返回结果可以是多个
function f1(){
var a =1; var b=2;
return [a,b];
}
var[a,b]=f1()
新的循环
for(var val of 数组名){ }
缺点:没有提供下标 不能修改原数组
只能遍历索引数组,不能遍历hash数组,不能遍历对象
set和map
1.set 可以用来去重数组
[...new set(arr)]
map
var map = new Map()
day15
正则表达式
定义字符串出现规则的表达式
何时使用
切割、替换、验证
如何使用
/正则表达式/
简单的正则表达式就是关键字 /no/后缀
后缀 g-->找全部 i-->忽略大小写
备选字符集 /^[备选字符集]$/
强调
一个中括号只管一维字符
正则表达式默认就不管后续了,做验证希望从头到尾完全匹配,这时需要加上^和$
特殊
如果备选字符集中ascii码是连续的,可以用-省略掉中间部分[0-9][A-Z][a-z]
预定义字符集
一位数字 \d
一位数字、字母、下划线 \w
一位空白字符 \s
一位除了换行外的任意字符 .
量词 规定了一个字符集出现的次数
有明确的数量
{n,m} 前面相邻的字符集 至少n个 做多m个
{n,} 前面相邻的字符集 至少n个 多了不限
{n} 前面相邻的字符集 只能n个
无明确数量
? 可有可无 最多一个
* 可有可无 多了不限
+ 至少一个 多了不限
选择和分组
选择 在多个规则中选一个
规则1|规则2
分组 将多个字符集临时组成一个子规则
(规则1|规则2)
匹配指定位置
开头 ^
结尾 $
特殊:两者同时使用,前加^ 后加$表示从头到尾 完全匹配
密码强度
预判公式
(?![0-9]+$) ---> 不能全由数字组成
(?![0-9a-z]+$) ---> 不能全由数字组成、小写字母组成,也不能全由数字和小写字母的组合组成
字符串中支持正则的API
切割
var arr = str.split("正则表达式")
替换
基础替换法
str = str.replace(正则表达式,"新内容")
高级替换法
str = str.replace(正则表达式,function(a,b,c){
a --->匹配到的关键字
b --->正则匹配到的关键字的下标
c ---> 原字符串
})
格式化
var str = "123456789123456789"
var reg = /\d{d}(\d{4})(\d{2})(\d{2})\d{4}/
id = if.replace(reg,function(a,b,c,d,e,f){
a --->匹配到的关键字
b --->第一个分组
c --->第一个分组
d --->第一个分组
e --->下标
f --->原数组
})
正则对象
创建:
直接量 var reg = /正则表达式/后缀
构造函数 var reg = new RegExp("正则表达式","后缀")
API
var bool = reg.test("输入的内容")
day16
animate.css
https://animate.style/
挑选喜欢的动画,把class放在需要的元素上
设置animation-duration:1s(想要的时间数)
day17
Object对象
对象具有属性和方法,都是预定义好的
面向对象
开发方式
面向过程:过程 - 开始 -> 结束,
面向对象:
何时使用,操作都封装在一个对象中
为什么使用 代码复用性
封装/创建/定义 封装自定义对象3种
直接量方式
var obj ={
"属性名":属性值,
"方法名":function(){}
}
强调
其实属性名和方法名的""可以不加
访问对象的属性和方法
obj.属性名 === obj["属性名"]
obj.方法名() == obj["方法名"]
访问不到的属性会返回undefined
可以随时的添加新的属性和方法
obj.属性名=新值;
obj。方法名=function(){}
遍历对象
使用 for in 循环,通过obj[i]拿到值
在对象的方法里使用对象的属性 ---->this.属性名
this 指向
单个元素绑定事件 ---> 这个元素
多个元素绑定事件 ---> 当前元素
定时器中的this ---> window
箭头函数中的this ---> 外部对象
函数中的this ---> 当前调用函数的
钩子函数中的this ---> 当前正在创建的对象
预定义构造函数方式
var obj = new Object();
obj.属性名= 新值
obj.方法名=function(){}
自定义构造函数方式
创建自定义构造函数
function 类名(v1,v2,v3){
this.属性名1=v1;
this.属性名2=v2;
this.属性名3=v3;
}
调用构造函数创建对象
var obj = new 类型(实参)
优点
便于维护,创建多个对象时方便
继承 父对象的成员,子对象可以直接使用
提高代码的复用性
多个对象公用的属性和方法集中到父对象中
如何找到原型对象,保存一类子对象共有属性和方法
对象名.__proto__;
构造函数名.prototype
面试题
两链一包 作用域链 原型链 闭包
day17
面向对象(笔试题)
判读是自有还是共有
判断自有 obj.hasOwnPrototype("属性名")
ture -> 自有属性
false -> 不是自有属性
判断共有
if(obj.hasOwnPrototype("属性名")==false){
自有;
}else{
if("属性名" in obj){
共有;
}else{
没有;
}
}
修改和删除 自有和共有
自有
obj.属性名=新属性值
delete obj.属性名
共有
原型.属性名=新属性值
delete 原型.属性名
如何为老IE的数组添加indexOf()方法
if(Array.prototype.indexOf===undefined){
Array.prototype.indexOf = function(key,start){
start === undefined &&(start=0);
for(var i =start;i<kei.length;i++){
if(this[i]==key){
return i;
}
}
return -1;
}
}
如何判断X是不是一个数组
判断X是不是继承自Array.prototype
Array.prototype.isPrototypeOf(x)
true ---> 数组
false --->不是数组
判断X是不是由Array这个构造函数创建
x instance of Array
true ---> 数组
false --->不是数组
Array.isArray(x) 只能数组可用
true ---> 数组
false --->不是数组
输出 对象的字符串 的形式
Object.Prototype.toString.call(x) === "[object Array]"
true ---> 数组
false --->不是数组
实现自定义继承
两个对象之间设置继承
子对象.__proto__ = 父对象
多个对象之间设置继承
构造函数名.prototype = 父对象
应该在开始创建对象之前就设置好继承关系
ES6 - class关键字:简化面向对象(封装、继承、多态)
class 类名 extends 老类名{
constructor(name,speed,rl){//放在constructor里面得都是自有属性
super(name,speed);//调用继承的老类的constructor函数
this.rl=rl;
}//放在constructor外面得都是共有方法
//还会继承到老类所有的API,也可以在此处添加属于自己的新的API
}
var obj=new 类名(实参,...)
Function - 闭包:
作用域:2种
1、全局:随处可用,可以反复使用,缺点:容易被污染
2、函数:只能在函数调用时内部可用,不会被污染,缺点:一次性的,使用完就会释放的。
函数的执行原理:
1、程序加载时:
创建执行环境栈(ECS):保存函数调用顺序的数组
首先压入全局执行环境(全局EC)
全局EC引用着全局对象window
window种保存着我们的全局变量
2、定义函数时
创建函数对象:封装代码段
在函数对象中有一个scope(作用域)属性:记录着函数来自的作用域是哪里
全局函数的scope都是window
3、调用前
在执行环境栈(ECS)压入新的EC(函数的EC)
创建出活动对象(AO):保存着本次函数调用时用到的局部变量
在函数的EC中有一个scope chain(作用域链)属性引用着AO
AO还有parent属性是函数的scope引用着的对象
4、调用时:
正是因为有了前面三步,才会带来变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错
5、调用完:
函数的EC会出栈,没人引用着AO,AO自动释放,局部变量也就释放了
闭包:希望保护一个可以【反复使用的局部变量】的一种词法结构,其实还是一个函数,只是写法比较特殊
何时使用:希望保护一个可以【反复使用的局部变量】- 私有化变量
如何使用:
1、两个函数进行嵌套
2、外层函数创建出受保护的变量
3、外层函数return出内层函数
4、内层函数在操作受保护的变量
强调:
1、判断是不是闭包:有没有两个函数嵌套,返回内层函数,内层函数再操作受保护的变量
2、外层函数调用了几次,就创建了几个闭包,受保护的变量就有了几个副本
3、同一次外层函数调用,返回的内层函数,都是在操作同一个受保护的变量
缺点:受保护的变量,永远都不会被释放,使用过多,会导致内存泄漏 - 闪退,不可多用!
四个事件需要防抖节流 - 共同:触发的飞快,但是我们不需要飞快的修改DOM树!
1、elem.onmousemove
2、input.oninput
3、window.onresize
4、window.onscroll
防抖节流公式:
function fdjl(){
var timer=null;
return function(){
if(timer){clearTimeout(timer);timer=null;}
timer=setTimeout(()=>{
操作;
},间隔毫秒数)
}
}
var inner=fdjl()
总结:两链一包:
1、作用域链:以函数的EC的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构
作用:查找变量,来带了变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错
2、原型链:每个对象都有一个属性.__proto__,可以一层一层的找到每个人父亲,形成了一条链式结构
作用:找共有属性和共有方法的,哪怕自己没有会悄悄的向上查找,如果最顶层也没有才会报错最顶层是Object的原型,甚至上面放着我们眼熟的API - toString,怪不得人人都可以使用
3、闭包:希望保护一个可以【反复使用的局部变量】的一种词法结构,其实还是一个函数,只是写法比较特殊
作用:专门用于防抖节流