js第四周学习笔记

116 阅读9分钟

animate.css和swiper插件

1、animate.css

  含义:是一个动画库,里面放着很多的动画,方便我们程序员使用
 如何使用:
  1、上网搜索animate.css
  2、下载
  3、将此文件引入到项目中
  4、挑选喜欢的动画,把class放到那个元素上
  5、放上class以后设置上animate-duration:3s;执行时长
  6、还要根据不同的动画,设置不同的初始效果,才会更好看

2、swiper插件:

 作用:专门的一个轮播插件,提供了html/css/js直接复制即可

面向对象开发:

1、Object:

  1、js中万物皆对象,同时js也是基于原型的面向对象语言
  2、对象具有属性和方法,都是用于定义好的,我们也可以自定义
  3、面向对象有三大特点:封装、继承和多态

1、开发方面:

 面向过程开发:开始——>结束,之前学的开发方式都是面向过程的,先干什么后干什么
 面向对象:对象(属性和方法)
 何时面向对象:以后任何一个操作都要封装在一个对象中,新手不推荐,难度大
 为什么要用面向对象开发:现实生活中的所有数据都必须包含在一个事物之中才有意义

2、封装/创建/定义 对象3种

1、直接量方式:

var obj ={
    "属性名":"属性值",
    ......
    "方法名":function(){操作}
}

强调

1、其实属性名和方法名的""可以省略不写,但是不建议,因为在后期JSON格式中必须要加上
2、访问对象的属性和方法:
obj.属性名;===obj["属性名"];
obj.方法名;===obj["方法名"]();

js中除了undefined和null,其余一切数据的底层都是哈希数组

3、访问到不存在的属性,返回undefined
4、可以随时添加新属性和新方法:
obj.属性名=新值;
obj.方法名=function(){}
5、使用for in 遍历以后拿到所有东西,obj[i]才能拿到对应的值
6、如果希望在对象的方法里使用自己对象的方法,写为this.属性名

难点:this的指向:
  1、单个元素绑定事件:this指向这个元素
  2、多个元素绑定事件:this指向当前触发事件的元素
  3、定时器中的this指向window
  4、箭头函数中的this指向外部对象
  5、函数中的this指向当前在调用此函数的那个对象
  6、构造函数中的this指向当前正在创建的对象

2、预定义构造函数:

var obj=new Object();//空对象

以上两种创建对象的方式都有一个缺陷:一次只能创建一个对象,适合在创建单个对象的时候使用第一种方法,批量创建对象选择以下这个方法

3、自定义构造函数方式:2步

1、创建自定义构造函数:
function 类名(name,age,hobby){
    this.name=name;
    this.age=age;
    this.hobby=hobby;
}

千万不要在里面创建方法,否则的话每个对象都会创建出来一个相同的方法,浪费内存,学习了继承以后可以解决这个问题

2、调用构造函数创建对象:
var obj=new 类名(实参,...);

面向对象的优点:
 1、逼格高,所有的属性和方法都保存在一个对象之中,更符合现实更有意义
 2、每个功能特地分开写——以便于后期的维护
 3、铁索连舟——一个方法触发多个方法联动

2、继承:父对象的成员(属性和方法),子对象可以直接使用

 为什么要继承:代码重用,提高代码的复用性,节约了内存空间,提升了网站的性能
 何时继承:只要多个字对象公用的属性和方法,都要集中定义在父对象之中

1、如何找到原型对象(父对象):

1、对象名.__proto__//必须要先有一个对象
2、构造函数名.prototype;//构造函数名几乎人人都有,除了Math和window
        new 构造函数名();Array,String,Date...

2、面试题:两链一包:作用域链、原型链、闭包

 原型链:
  每个对象都有一个属性__proto__,可以一层一层的找到每个人的父亲,形成的链式结构就是原型链
  它可以找到父对象的成员(属性和方法),作用:找到共有属性和方法
  最顶层是Object的原型,上面有一个我们熟悉的toString方法,怪不得人人都可以用toString方法

3、有了原型对象,可以设置共有属性和方法

4、继承中的笔试题:

1、判断公有还是自有:

 1、判断自有:obj.hasOwnPropety("属性名");如果结果为true则为自有

obj.hasOwnPropety("属性名");

 2、判断公有:if(obj.hasOwnPropety("属性名")===false&&"属性名" in obj) 此处的in是一个关键字,会自动查找整条原型链上的属性

if(obj.hasOwnPropety("属性名")===false&&"属性名" in obj){
        公有
}else{
        自有
}

判断自有还是公有的完整公式:

 if(obj.hasOwnPropety("属性名")){
         自有
 }else{
 if("属性名" in obj){
         公有
 }else{
         没有
 }
 }

2、修改和删除:自有和公有

 修改:
  自有:obj.属性名=新值;
  公有:原型对象.属性名=新值;
 删除:
  自有:delete obj.属性名;
  公有:delete 原型对象.属性名;

3、如何为老IE的数组添加indexOf方法:

if(Array.prototype.indexOf===undefined){
    Array.prototype.indexOf=function(key,starti){
        if(starti===undefined){
            starti=0;
        }
        for(var i=starti;i<this.length;i++){
            if(this[i]==key){
                return i;
            }
        }
        return -1;
    }
}
arr.indexOf();

4、判断X是不是一个数组:4种方法,千万不能用typeof方法,此方法只能检查原始类型,不能检查一用类型,返回的是一个Object

1、判断X是不是继承自Array.prototype:
Array.prototype.isPrototypeOf(X);
=>返回为true则是一个数组
2、判断X是不是由Array这个构造函数创建
X.instanceof Array
3、Array.isArray(X)
Array.isArray(X)//只有数组能用这个方法
4、输出[对象字符串格式]的方式

 在Object的原型上有一个最原始的toString的方法
 原始toString的输出方式:[object 构造函数名]
多态:同一个方法,不同的人使用有不同的效果,它有多种形态
 固定套路:

Object.prototype.toString.call/replay(X)===>[object Array]
5、实现自定义继承:

 1、两个对象之间设置继承:

子对象.__proto__=父对象

 2、多个对象之间设置继承:

构造函数名.prototype=父对象;

  此方法要掌握好时机,设置好继承关系后才能创建对象

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

语法:

class 类名 extends 老类类名{
    constructor(name,age,hobby){//自有属性放在constructor中
        supper(name,age);//此处放的是老类中的公有属性
        this.hobby=hobby;//添加一身多于老类的属性
    }
    公有方法//constructor外放的是公有方法,亦可以自己新建
}

3、****闭包****

1、作用域:2种

 1、全局:随处可用,可以反复使用。缺点:容易被污染。
 2、函数:只能在函数中调用,不会被污染。缺点:一次性的,是会自动释放的

函数的执行原理:

 1、函数加载时:   创建执行环境栈(ESC):保存函数的调用顺序的数组
  首先压入全局执行原理(全局EC)
  全局EC引用着全局对象window
  window中保存着我们的全局变量
 2、定义函数时:
  创建函数对象:封装代码段
  在函数对象之中有一个scope(作用域)属性:记录着我们函数自己的作用域是哪里
  全局函数的scope都是window
 3、调用前:
  在执行环境栈(ESC)中压入新的EC(函数的EC)
  创建出活动对象(AO):保存着本次函数调用时用到的局部变量
  在函数的EC中有一个scope chan(作用域链)属性引用着AO
  AO有一个parent属性是函数的scope引用着的对象
 4、调用时:
  正是因为前面3步,才带来了变量的使用规则:优先使用自己的,自己没有找全局。全剧没有就报错
 5、调用完:
  函数的EC会出栈,没人引用AO,AO会自动释放,局部变量也就释放了

**闭包**:希望保护一个可以反复使用的变量的时候

 如何使用:
  1、两个函数进行嵌套
  2、外层函数创建出需要保护的变量
  3、外层函数return出内层函数
  4、内层函数再操作受保护的变量
强调:
  1、判断是不是闭包:有没有两个函数嵌套,外层函数返回内层函数,内层函数操作着受保护的变量
  2、外层函数调用了几次,就创建了几个闭包,受保护的变量就有几个副本
  3、同一次外层函数调用,返回的内层函数,都是在操作同一个受保护的变量
 缺点:受保护的变量,永远都不会被释放,使用过多,会导致内存泄漏——不可多用
 问题:使用场景:——防抖节流
  三个事件:
   1、鼠标移动事件:elem.onmousemove
   2、input输入方法:input.oninput
   3、窗口大小更改事件:onresize
 防抖节流的公式:

function fdjl(){
    var timer=null;
    return function(){
        if(clearTimeout(timer);timer=null){
            timer=setTimeout(()=>{
                操作;
            },500)
        }
    }
}

总结:两链一包:
 1、作用域链:以函数的EC的spoce chain属性为起点,经过AO,逐级引用,形成一条链式结构,我们称之为作用域链
  作用:查找变量,带来了变量的使用规则:优先使用自己的,自己没有找全局要,全局没有就报错
 2、原型链:每个对象都有一个属性叫做.proto,可以一层一层的找到每个对象的原型对象,最顶层的就是Object的原型,形成一条链式结构,我们称之为原型链
  作用:查找属性和方法,哪怕自己没有也会顺着原型链向上找,之所以人人都能用toString方法,就是因为它在最顶层
 3、闭包:希望保护一个可以反复使用的局部变量的一种词法结构,其实是一个写法较为特殊的函数
  作用:专门用于防抖节流