发表于: 2021-11-29 23:15:28
0 793
今天完成的事情:
看了JS知识点
明天计划的事情:
继续看知识点
遇到的问题:
慢慢收集问题
收获:
如何理解JS作用域与作用域链?
(1)背景介绍:
当js代码运行在中的时候,浏览器会为其提供为JS代码提供执行的环境,这个环境叫作用域也叫栈内存。离开了作用域代码就是一堆字符串,没有什么作用。因为没有作用域代码就不能正常执行,所以作用域也可以理解为变量与函数的可访问范围。
(2)知识剖析:
作用域分为全局作用域,私有作用域和块级作用域。
作用范围在整个页面的作用域叫做全局作用域,前端用window表示。在全局作用域下声明的变量任何地方都可以使用,全局作用域的生命周期跟页面一样长,只有页面销毁全局作用域才销毁。
函数执行时所形成的作用域叫做私有作用域,私有作用域里面的变量外面不能调用,全局作用域与私有作用域的区别就是,全局作用域是公共公园,里面的东西都是公共设施谁都可以玩,私有作用域是私人庭院,里面的设施外人是不能随便碰的。
块级作用域是ES6的概念,也相当于一个私有作用域,但是以大括号作为作用域的范围 在ES6语法中,一般用大括号包起来的都是块级作用域,if大括号是块级作用域,for循环体也是块级作用域,初始值设置的变量是当前本次块级作用域中的变量。
对象不是块级作用域,就是一个值。
(3)常见问题:
私有变量没有用关键字声明影响全局变量。
在一个私有作用域中,如果不带关键字声明就不是私有变量,这时他会向他的上级作用域查找,看是否为上级的变量,如果不是继续向上级查找,一直找到全部局变量位置,我们管这种查找机制叫做作用域链。
(4)解决方案:
给私有变量用关键字声明即可。
(5)编码实战:
var b =12
function op (){
let b =13
}
op()
console.log(b)
op里的b因为在私有作用域里,所以外面调用不了,这里的console.log还是12
let a =12;
function q(){
function d(){
function k(){
console.log(a)
}
k()}
d()}
q()
k函数里因为没有变量a,根据作用域链的机制console.log里的a会一直向上级作用域查找,一直找到全局作用域里的a,所以这里的a是12
(6)拓展思考:
私有作用域的释放与闭包
一般情况下,当函数执行完成,所形成的私有作用域都会自动释放掉,在私有作用域存储的值也会释放掉,但是也有特殊情况不销毁,1.函数执行完成,当前形成的私有作用域中,某些内容被私有作用域以外的变量占用了,此时私有作用域不能释放,也就是说私有作用域里边的东西被外边占用了,就不销毁。
举个例子
function lo(){
function ll(){
console.log(12)
}
}
lo()
这里函数lo执行完毕之后其私有作用域是要销毁的,但是假如把里面的ll函数赋值给一个全局变量
let a =ll,这时候lo函数所形成的私有作用域就不会销毁,因为lo函数里面的ll函数被赋值给了一个全局变量,如果销毁了那ll函数也就不会存在了。
私有作用域有两大作用,一个是保护,一个是保存。保护就是函数执行会形成一个私有的作用域,外面无法直接获取里面的变量值,此时私有作用域把私有变量保护了起来,外面不管发生什么都不会影响里面的变量。保存就是像jQ这样吧所有的方法放到一个函数中保存起来,这种保存机制叫做闭包。
举个例子
假如有一个li列表,要求我随便点击哪一个它的背景颜色变成红色,如果你是这样写那就错了
let box =document.getElementsByTagName("li")
for(var i=0;i<box.length;i++){
box[i].onclick=function(){
box[i].style.backgroundColor='red'
}
}
因为这个函数绑定点击事件的时候并没有触发,它是点击的时候才会触发,所以绑定的时候函数里面的i是字符串i,他不是变量i,等到点击触发函数的时候,此时的i的值早就不是跟索引号一样了。这个问题可以用闭包的原理解决。
let box =document.getElementsByTagName("li")
for(var i=0;i<box.length;i++){
box[i].onclick= (function(i){
return function(){
box[i].style.backgroundColor='red'
}
})(i)
}
这样写才是对的,点击事件绑定一个自执行函数,然后把变量i当做实参传入到自执行函数里,因为函数执行会自动形成一个私有的作用域,所以当全局变量i传进去之后就会变成了私有变量i,因为return返回一个函数绑定了事件,所以自执行函数的作用域在函数执行完不能销毁,此处体现了作用域的保存机制,把变量i保存了下来。当点击触发里面的函数时里面所调用的变量i就是自执行函数所保存的变量i。
评论