javascipt变量作用域分为两种:局部作用域(函数作用域),全局作用域。
一、变量的作用域
函数内部可以读取全局变量。
全局作用域无法读取局部作用域中的局部变量
二、如何获取局部作用域中的局部变量和方法点击查看代码
function fn1(){
var n =100;
function fn2(){
console.log(n);//100
}
}
三、闭包
有权访问另一个局部作用域(函数作用域)中的变量 的函数。简单来说就是函数在执行过程中,返回了另一个函数或引用类型。使得可以在函数外部访问函数内部变量。
四、闭包的必要条件
1.函数在调用时返回了另一个函数或引用类型
2.返回的函数或引用类型中,使用了父作用域中的变量或方法
3.函数外有变量或其他数据类型引用了返回值
五、闭包的优缺点
优点:1.保存关联的AO对象,即父作用域
2.允许函数外部访问函数内部变量
3.可以有效减少全局变量的使用
缺点:1.父作用域关联的AO对象会一直存储在内存中得不到释放,易导致内存泄漏。
2.由于函数外部可以访问函数内部变量,数据不安全
六、闭包的作用
1.循环绑定点击事件。绑定点击事件是异步操作。for循环是同步操作,当页面加载成功就会直接进入循环,等到点击时,i的值已经变为selector.length了。使用闭包来保存关联的AO对象,即每一个循环的父作用域
点击查看代码
for(var i = 0;i < selector.length;i++){
(function (i){
selector[i].onclick = function(){
console.log(lis[i].textContent);
}
})(i)
点击查看代码
let timer = null;
btn.onclick = function () {
clearTimeout(timer);
timer = setTimeout(function () {
console.log("上传");
}, 300)
}
点击查看代码
btn.onclick = function () {`
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(function () {
console.log("上传");
}, 300)
}
}()
闭包封装
function debounceFn(callback, delay) {
let timer = null;
return function (...list) {
clearTimeout(timer);
let that = this;
timer = setTimeout(function () {
callback.apply(that, list)
}, delay);
}
}
btn.onclick = debounceFn(function (e) {
console.log("上传");
}, 300);
3.函数节流 如果函数高频率触发,降低触发的频率
例如:滚动条滚动事件。
window.onscroll = function () {
console.log("滚动了"); //一滚动便触发
}
解决办法:
点击查看代码
a.
let start = Date.Now(); // 页面加载成功的时间
window.onscroll = function () {
let Now = Date.Now(); // 开始滚动时间
if (Now - start >= 300) {
console.log("正在滚动");
start = Now;
}
}
b.闭包
window.onscroll = (function () {
let start = Date.Now();
return function () {
let Now = Date.Now();
if (Now - start >= 300) {
console.log("正在滚动");
start = Now;
}
}
})()
// 闭包封装
function throttle(callback, delay) {
let start = Date.Now();
return function (...list) {
let Now = Date.Now();
if (Now - start >= delay) {
callback.apply(this, list);
start = Now;
}
}
}
window.onscroll = throttle(function (e) {
console.log("滚动了")
}, 300)