js第四周学习

146 阅读7分钟

animate.css动画库

网址animate.style/

使用步骤:

  • 下载
  • 引入animate.css
  • 把class放在需要动画的元素上
  • 设置animation-duration执行时间,自身提供class:animate__animated只能为1秒

swiper插件(轮播插件)

  • 下载插件包
  • 引入js和css
  • 复制需要的轮播代码

运动(动画)函数

function animate(selector,obj){
    var elem=document.querySelector(selector);
    for(var i in obj){
        console.log(i)
        elem.style[i]=obj[i];
    }
}

高德/百度地图

  • 搜索百度/高德地图开放平台
  • 应用管理->我的应用->创建应用->应用名称随意->应用类型选择浏览器端->白名单:0.0.0.0/0
  • 开发文档,JavaScriptAPI->示例DEMO->挑选你喜欢的地图,复制到你的项目之中
  • 修改CSS/JS代码,查询在线的经纬度(百度地图拾取坐标系统)

注意: 地图可以混搭使用,但是再某次升级过后,出现了GL地图和普通版地图,两者不可以混搭使用,只有GL和GL混搭,普通版和普通版混搭

封装自定义对象

直接量方式

var obj={
    '属性名':'属性值',
    '方法名':function(){操作},
}
  • 属性名和方法名可以不加''和""
  • 访问对象属性和方法
    • 对象名.属性名 <-->对象名['属性名']
    • 对象名.方法名() <-->对象名['方法名']()
  • 访问不存在的属性返回undefined
  • 添加新属性和方法
    • obj.属性名=属性值
    • obj.方法名=function(){}
  • 遍历对象,使用for in循环
  • 在对象里面使用对象自己的属性,必须this.属性名

this的指向

  • 单个元素绑定事件this-->这个元素
  • 多个元素绑定事件this-->当前元素
  • 定时器this-->window
  • 箭头函数this-->外部对象
  • 函数中this-->谁在调用,this就是谁
  • 自定义构造函数this-->正在创建的对象

预定义构造函数

var obj=new Object();//空对象
obj.属性名=属性值;
obj.方法名=function(){}

自定义构造函数

//创建自定义构造函数
function 类名(name,age,hobby){
    this.name=name;
    this.age=age;
    this.hobby=hobby;
}
//调用构造函数创建对象
var obj=new 类名(实参,)

继承

找原型对象

  • 对象名.__proto__;//必须要先有一个对象
  • 构造函数名.prototype//构造函数人人都有除了Math和Window,new 构造函数名()

设置共有属性和共有方法

  • 原型对象.属性名=属性值;
  • 原型对象.方法名=function(){}

原型链

每个对象都有一个属性__proto__可以一层一层的找到父类,形成链式结构,叫原型链

判断自有还是共有

  • 判断自有pbj.hasOwnProperty('属性名')
  • 判断共有
    if(obj.hasOwnProperty("属性名")){
        console.log("自有")
    }else{
        if("属性名" in obj){
            console.log("共有");
        }else{
            console.log("没有");
            }
    }

修改和删除:自有和共有

  • 自有
    • 修改obj.属性名=新值
    • 删除delete obj.属性名
  • 共有
    • 修改原型.属性名=新值
    • 删除delete 原型.属性名

判断是不是数组

判断x是不是继承自Array.prototype

Array.prototype.isPrototypeOf(x); 结果为true,说明是数组,结果为false,说明不是数组

判断x是不是由Array这个构造函数创建的

x instanceof Array 结果为true,说明是数组,结果为false,说明不是数组

Array.isArray(x) - 老IE不支持,只有数组有此操作

结果为true,说明是数组,结果为false,说明不是数组

*输出【对象的字符串】形式

在Object的原型上保存着最原始的toString(); 最原始的toString()输出的形式:[object 构造函数名]

实现自定义继承

  • 两个对象之间设置继承子对象.__proto__=父对象
  • 批量设置继承:构造函数名.prototype=父对象
    • 注意时机:应该在创建对象之前设置好继承关系

class关键字 - Es6简化面向对象(封装、继承、多态)

class 类名 extends 老类{
    constructor(name,speed,rl){//写在constructor里面的其实就是自有属性
    super(name,speed);
    this.rl=rl;
    }
//共有方法放在老类
function 方法名(){}
}

作用域链

  • 全局:随处可用,可以反复使用。缺点:容易被污染
  • 函数:只能在函数内部可用,不会被污染。缺点:一次性的,使用完就会释放

执行原理

程序加载时

  • 创建执行环境栈(ECS):保存函数调用顺序的数组
  • 压入全局执行环境(全局EC)
  • 全局EC引用着全局对象window
  • window中保存着我们的全局变量

定义函数时

  • 创建函数对象:封装代码段
  • 在函数对象中有一个scope(作用域)的属性:记录函数来自的作用域
  • 全局函数的scope都是window

调用前

  • 在执行环境栈(ECS)中压入新的EC(函数的EC)
  • 创建出活动对象(AD):保存着本次函数调用时的局部变量
  • 在函数的EC中有一个scope chain(作业域链)属性引用着AO
  • AO还有parent属性时函数的scope引用着的对象

调用时

变量使用规则:先使用局部,局部没有找全局,全局没有报错

调用完

函数的EC会出栈,没人引用着AO,AO自动释放,局部变量也释放

闭包(保护一个可以反复使用的局部变量)

  • 两个函数进行嵌套
  • 外层函数创建出受保护的变量
  • 外层函数return出内层函数
  • 内层函数操作受保护的变量

注意:用一次外层函数调用,返回的内层函数都是操作同一个受保护的变量

缺点:受保护的变量,永远不会被释放,使用过多会导致内存泄漏

使用场景:防抖节流(触发的飞快,飞快的修改DOM树)

  • elem.onmousemove
  • input.oninput
  • elem.onclick
  • window.onscroll
  • window.onresize
function 方法名(){
    var timer=null;
    return function(){
        if(timer!=null){
            clearTimeout(timer)
        }
        timer=setTimeout(()=>{
            操作
        },1000)
    }
}

保护对象的属性和方法

对象每个属性都具有四大特性

{
    value:值l;//保存值的地方
    writable:true/false,//控制属性是否被修改,默认true
    enumerable:true/false,//控制属性是否被循环遍历到,默认true
    configurable:true/false,//控制属性是否被删除,默认true
 }

修改四大特性

  • Object.definProperty(对象名,'属性名',{四大特性})一次只能保护一个属性的四大特性
  • Object.defineProperties(对象名,{'属性名':{四大特性},....})一次可以保护多个属性

三个级别

  • 防添加Object.preventExtensions(x)
  • 防添加和删除Object.seal(x)
  • 防添加和删除和修改Object.freeze(x)
Object.defineProperty(对象名,"属性名",{
    get:()=>{
	console.log("获取数据会进行拦截")
	},
    set:(v)=>{
	//v就是你设置的东西
	console.log("设置数据会进行拦截")
	}
})

对象的深拷贝和浅拷贝

  • 浅拷贝(按值传递)
var obj1={'name':'ob'}
var obj2=obj1;
  • 深拷贝:两者互不影响
//第一种方法
var obj1={'name':'obj'}
var obj2={...obj1}
//第二种方法
var obj2=JSON.parse(obj2)
//第三种方法
var obj2=eval('('+obj2+')')

Error对象(错误)

错误类型

  • 语法错误:SyntaxError - 一定是你的符号/语法写错了
  • 引用错误:ReferenceError - 没有创建就去使用了
  • 类型错误:TypeError - 不是你的方法,你却去使用了,最有可能的就是你拿到了undefined和null
  • 范围错误:RangeError - 只有API会遇到:num.toFixed(d);//d取值范围:0~100之间

错误处理

try{
    //可能报错的代码
}catch(err){
    //发生错误执行的代码
}

try...catch...性能差,可以用分支结构代替

自定义错误:报错就不会执行后续代码

`throw new Error('自定义错误信息')

柯里化函数

function add(a){
    return function(b){
        return function(c){
           console.log(a+b+c);
        }
     }
}
add(3)(5)(7)

匿名函数

  • 自调(function(){操作})()
  • 回调elem.on事件名=function(){}

事件轮询

宏任务

  • 定时器:setInterval 和 setTimeout
  • AJAX - 他是前端和后端连接的关键点,他也是一个异步宏任务

微任务

function ajax1(resolve){
    setTimeout(()=>{
        console.log("<h1>页面的头部</h1>");
	resolve();//放行函数
    },Math.random()*5000);
}
function ajax2(){
    return new Promise(function(resolve){
        setTimeout(()=>{
            console.log("<h1>页面的身体</h1>");
            resolve();	
         },Math.random()*5000);
    })
}
function ajax3(){
    return new Promise(function(resolve){
	setTimeout(()=>{
            console.log("<h1>页面的脚部</h1>");
            resolve();
        },Math.random()*5000);
    })
}
new Promise(ajax1).then(ajax2).then(ajax3);