JavaScript高级篇之part5

javascript高级与面向对象笔记整理,接part4篇!!

词法作用域

词法作用域的概念

变量的作用域在代码写好的时候就已经可以确定,这种作用域就是词法作用域

  • JavaScript 中没有动态作用域
  • JavaScript 中没有块级作用域

变量提升

JS代码执行分两个阶段,首先进行预解析,再执行
在预解析阶段,系统会将所有的变量声明以及函数声明提升到当前作用域的最顶上

  • 当函数同名的时候,都会提升,但是后面的函数会将前面的函数覆盖
  • 当函数和变量同名的时候,只会提升函数声明,变量声明会被忽略
  • 变量提升是分作用域的
  • 变量提升是分段( script 标签)
  • 函数表达式是不会被提升,提升的只是变量的声明。 var func= function(){};
  • 条件式函数声明,根据浏览器不同,提升的情况不同,最新的浏览器中都不会进行提升

作用域链

js 中只有函数可以限定作用域,然后,函数中又可以声明函数,这样就形成了一个由内向外进行访问的链式结构,这个结构就叫做作用域链

如何绘制作用域链

  1. 先画一条直线,表示0级作用域链,也就是全局作用域
  2. 再在全局作用域中查找变量以及函数的声明,将所有找到的这些成员以小方块的形式放在0级作用域链上
  3. 如果全局作用域中有函数成员,那就从该函数中在引出一条线,表示1级作用域链
  4. 再去1级作用域中进行查找变量以及函数的声明,在把他们画出来,
  5. 如果还有函数,就接着去找。。。。直到没有函数为止

变量的搜索原则

  1. 首先在当前作用域中进行查找,如果找到了就直接使用
  2. 如果没有找到,就去上一级作用域中进行查找,如果找到了就直接使用
  3. 果没有找到,就继续往上查找,直到找到全局作用域为止

如何分析面试题

  1. 先进行提升处理(把提升后的代码写出来)
  2. 然后根据作用域及作用域链还有变量搜索原则进行分析

闭包

  • 语文解释:封闭的包裹结构
  • js的解释:函数就是一个闭包

闭包要解决的问题是什么?

函数内部的数据无法被外界直接访问!

如何解决?

在函数内部返回一个函数,用来操作该函数内部的数据。

闭包的原理(作用域)

函数中的变量无法被上一级作用域访问,但是可以被下一级作用域访问。

闭包的基本模型

1
2
3
4
5
6
function func(){
var name = "";
return function(){
return name;
}
}

如何访问多个数据?

返回一个对象,对象中包含对所有数据的设置和访问的方法,在函数外部接收到该对象之后,就可以操作函数内部的数据

点击事件的注册问题

如果在for循环中使用循环的控制变量i来处理点击事件中的内容,那么这个 i 在点击事件触发的时候,循环已经结束,i 已经变成了最后一个值,所以会不准确

如何解决

在点击事件的处理函数内部,访问的时候,不要去使用 i,而是使用这个函数自己的一个私有的数据。
所以需要使用一个拥有自己的变量的函数来做点击事件的处理函数。

这个函数需要通过闭包来创建。
1
2
3
4
5
6
function f1(j){
return function(){
console.log(j); //这里的j就是只有这个函数可以访问的一个私有的变量
}
}

上面的函数调用之后的返回值,就拥有了自己独立的变量,我们可以使用它来做点击事件的处理函数

setTimeout的回调函数执行时间问题

setTimeoutsetInterval 中的回调函数,会在所有的主逻辑代码执行完之后,才依次检查执行时间是不是到了,到了就会执行

当把 setTimeout 放在一个for循环语句中的时候,如果在回调函数中使用了循环中变量i
那么,当 setTimeout 的回调函数执行的时候, for 循环已经执行完毕,i已经是最后一个值

解决办法

回调函数不应该去使用 for 循环中的 i ,而是使用自己的一个私有变量

1
2
3
4
5
6
function f(j){
return fucntion(){
console.log(j)
}
}
setTimeout(f(i),0);