javascipt变量作用域分为两种:局部作用域(函数作用域),全局作用域。
一、变量的作用域
函数内部可以读取全局变量。
var n = 100 //全局变量; function fn(){ console.log(n) } fn() // 100
全局作用域无法读取局部作用域中的局部变量
function fn(){ var n = 100; //一定要带上var申明,否则是全局变量 } console.log(n);//错误
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 btn = document.querySelector("button"); btn.onclick = function () { console.log("上传"); }
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)