Function作用域:
1.全局作用域:随处可用,可以反复使用 缺点:容易被污染;
2.局部作用域:只能在函数被调用时内部可用,不会被污染, 缺点:一次性的,会自动释放;
函数的执行原理:
1、程序加载时:
创建执行环境时(ECS) -> 保存函数调用顺序的数组;
首先压入全局执行环境(全局EC);
全局EC引用着全局对象window
window中保存着全局变量;
2.定义函数时:
创建函数对象 -> 封装代码段;
在函数对象中有一个scope(作用域)属性:记录着函数来自的作用域是哪里
全局函数的scope都是window。
3.调用前:
在执行环境栈(ECS)压入新的EC(函数的EC)
创建活动对象(AO) -> 保存着本次函数调用时要用到的局部变量
而在这个EC中有一个scope chain(作用域链)属性引用AO
AO有一个parant属性是函数的scope引用的对象
4.调用时:
正式因为有了前三个步骤,我们才有了变量的使用规则 -> 优先使用局部的,局部没有使用全局的,全局没有就报错;
5.调用完:
函数的EC会出栈,没人引用AO,AO会自动释放,所以局部变量也就释放了。
两链一包:
作用域链:
以函数的EC中的scope chain属性为起点,经过AO,逐级引用,形成了一条链式结构,就称之为叫做作用域链;
作用:变量的使用规则,查找变量;
闭包:希望保护一个可以【反复使用的局部变量】的一种词法结构,其实函数一个函数,写法和以后有点不一样;
何时使用:希望保护一个可以【反复使用的局部变量】
如何使用:4步
1.两个函数相互嵌套
2.外层函数创建出受保护的变量
3.外层函数要return返回的内层函数
4.内层函数要操作受保护的变量
强调:
1.判断是不是闭包,有没有两个函数嵌套,返回内层函数,内层函数在操作受保护的变量;
2.外层函数调用了几次,就创建了几个闭包,受保护得变量就有了几个副本;
3.同义词外层函数调用,返回得内层函数,都是在操作同一个受保护得变量;
缺点:受保护的变量,永远不会被释放,使用过多,造成内存泄漏;
使用场景:防抖节流
有三个事件做防抖节流,实行的速度非常快,减少DOM树的渲染
1.elem.onmousemove 鼠标移动事件
2.input.oninput 输入框内容有变化时会触发
3.window.onresize 当前窗口的尺寸发生了变化时就会触发;
公式:
elem.on事件名=function(){
inner();
}
function fdjl(){
var timer=null;//1 2 3 - 定时器序号
return function(){
if(timer){clearTimeout(timer);timer=null}
timer=setTimeout(function(){
//操作
},1000)
}
}
var inner=fdjl();
对象:
Array/String/Function/Math...对象具有属性和方法,都是预定义好的
现在学习自定义对象:
面对对象:Object:三大特点:封装,继承,多态
1.开发方式:
面向过程:开始 -> 结束 我们一直以来的开发方式都是面向过程:先干什么在干什么最后干什么
面向对象:对象(属性和方法),js有一句话万物皆对象,假设一个人是一个对象的话;
属性:姓名,性别,身高,体重,爱好。。。
方法:吃法,睡觉,拉粑粑,跑步,拳击,打游戏。。。
为什么要面向对象:现实生活中所有的数据都要保存到一个事务中才有意义;
何时使用面向对象:以后做任何操作都要封装在一个对象中 - 只是建议 ; 对新手不太友好
2.封装对象:创建自定义对象:三种
1.直接量方式:
var obj={
"属性名":"属性值",
...
"方法名":function(){},
...
}
强调:
1.其实属性名和方法名的引号可以省略不写,但是建议暂时写上,因为后续要学习JSON数据格式,要求必须加上""
2.访问对象的属性和方法:
对象名.属性名 === 对象名["属性名"]
对象名.方法名 === 对象名["方法名"]();
JS中的一切对象的底层都是hash数组
3.访问到不存在的属性或者方法时会返回undefined
4.可以后期随时随地的添加新属性和新事件
5.如果希望遍历出对象中的所有东西
for(var i in 对象名){
对象名[i]
}
6.如果你希望在对象的额【方法】中使用对象自己的属性:写为this.属性名
难点:this的指向:
1.单个元素绑定事件: this -> 这个元素
2.多个元素绑定事件: this -> 当前触发事件的元素
3.函数中使用this: this -> 谁在调用此方法.this就指向谁
4.定时器this: this -> window
5.箭头函数this: this -> 外部对象
2,预定义构造函数方式:
var obj=new Object(); 创建出一个空对象
需要自己后续添加属性和方法
obj.属性名="属性值";
obj.方法名=function(){}
以上两种方法创建都有一个缺陷:一次只能创建一个对象,适合创建单个对象的时候使用(第一种方式)
3,自定义构造函数方式:
1,创建自定义构造函数:
function 类名(name,age,salary){
this.name=name;
this.age=age;
this.salary=salary;
}
2,反复调用自定义构造函数创建出对象
var xxx=new 类名("实参",.....)
面向对象:
优点:
1.逼格高,所有的属性和方法都是保存在一个对象之中 --- 更符合生活:代码风格,代码速度都凸显逼格
2.每个功能特地的分开写 --- 便于维护
3.链式反应 --- 一个方法触发多个方法联动
缺点:
对新手的不友好 --- this 的指向;