JS第三周——day4

78 阅读4分钟

1、闭包

作用域:2种

1、全局作用域:成员 随处可用,可以反复使用,但是容易被污染

2、函数作用域:成员 只有当前函数调用时内部可用,调用完了,就会释放了,一次性

函数的执行原理:

1、程序加载时:

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

2、定义函数时:

创建函数对象:封装函数的定义
在函数对象中创建scope属性,记录着自己来自的作用域
全局函数的scope都是window

3、调用函数前:

在执行环境栈ECS压入新的函数的EC
创建活动对象AO:保存着本次函数调用时用到的局部变量
在EC中添加scope chain属性引用AO
设置AO的parent属性为函数的scope引用的对象

4、调用时:

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

5、调用完:

函数的EC会出栈,AO会自动释放,局部变量也就自动释放了

作用域链scope chain:

以EC中的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构,就称之为叫做作用域链

作用:查找变量

闭包目的:保护一个可以【反复使用的局部变量】的一种词法结构

结合了全局和局部的优点

唯一的缺点:受保护的变量永远不能释放,用多了会导致内存泄漏

尽量的少用:只有一个点会用到防抖节流

1、创建一个外层函数

2、在其中创建一个受保护的局部变量

3、外层函数调用要返回内层函数,此内层函数在操作受保护的变量

固定语法:

function 外层函数(){
    受保护的变量;
    return function(){
        不断的操作受保护的变量
        return 结果;
    }
}	

var 内层函数=外层函数();

正式开发:防抖节流:减少DOM树的渲染,DOM数据渲染的次数越频繁页面的效率越底下

需要去做防抖节流的3个事件:

1、elem.onmousemove - 鼠标移动事件,每次移动就会触发
2input.oninput - input每次修改内容就会触发
3、window.onresize - 屏幕每次改变大小就会触发

固定公式:

function fdjl(){
    var timer=null;
    return function(){
    //判断有没有定时器,如果有定时器就清除定时器
     if(timer){clearTimeout(timer)}	
     timer=setTimeout(function(){
        //你要做的操作
      },毫秒数)
console.log(timer);//定时器的序号
    }
}

var animate=fdjl();

2、Object:面向对象开发方式

三大特点(封装、继承、多态)

什么是面向对象:

在程序中都使用对象来描述现实中的一个事物,现实中事物的属性,代码中就成为了对象的属性,现实中事物的方法,代码中就成为了对象的函数,现实中所有数据都必须包含在一个事物中才有具体的意义

1、封装/创建/定义/声明/实例化:

自定义创建对象:3种

1、*直接量方式:(适合创建一个对象)

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

强调

①其实属性名和方法名的""可以省略,但是不推荐,以后JSON必须加""

②如何访问对象属性和方法

obj.属性名 === obj["属性名"]
obj.方法名(); === obj["方法名"]();
强烈建议:使用.去访问

③访问到不存在的属性:返回undefined

④也可以在后续随时随提的添加自己想要的东西

特殊:this在当前对象的方法内,指向的当前调用方法对象

面试题:this指向:

①单个元素绑定事件 this->单个元素

②多个元素绑定事件 this->当前触发的元素

③函数中也可以使用 this->当前调用函数的对象

④构造函数中如果出现了this this->当前正在创建的对象

⑤定时器中 this->window

只要以后对象的方法想要使用对象自己的属性,那么就写为this.属性名

2、预定义构造函数:

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

以上两个方法仅适合创建单个对象,如果想要创建多个对象则太繁琐

3、*自定义构造函数:2步(适合创建多个对象)

①创建一个构造函数

function 类名(形参,...){
    this.属性名=形参1;
    this.属性名=形参2;
    ...
}

②反复调用构造函数创建出多个对象

var xxx=new 类名(实参,...)