作用域与闭包

演讲者:交互开发课题组

内容提纲

  1. 作用域
  2. 提升
  3. 闭包
  4. 案例练习

作用域

  • 表达式级别作用域
  • 块作用域
  • 函数作用域
  • 全局作用域

表达式级别作用域

  • 只能使用一次,执行完之后不能再访问
    • 字面量(直接量)
    • 匿名函数
<script type="text/javascript">
//直接量,程序中直接使用的数据值
"helloworld";
//匿名函数
window.setTimeout(function(){console.log('hello world')},1000);
</script>

块级作用域

  • JS没有块级作用域
<script type="text/javascript">
//JS没有块级作用域
for (var i = 0; i < 5; i++) {
    console.log(i);
}
console.log(i);
</script>

函数作用域

  • 函数里面的变量是局部变量
<script type="text/javascript">
//函数里面的变量是局部变量
function go () {
    var a=0;
    console.log(a);
}
go();
console.log(a);
</script>

全局作用域

  • 在代码中任何地方都能访问到的对象拥有全局作用域
    • 最外层函数和在最外层函数外面定义的变量拥有全局作用域
    • 所有window对象的属性拥有全局作用域
    • 提升过的变量和函数
<script type="text/javascript">
//全局作用域
//最外层定义的变量
var name="tom";
//最外层定义的函数
function sayHello () {
    console.log("hello");
}
//window对象拥有全局作用域
window.alert(window.location);
//提升过的变量和函数
function say () {
    str="hello";
}
say();
console.log(str);
</script>

提升

  • 变量和函数从它们在代码中出现的位置被“移动”到最上面。
  • 变量提升
    • 作用域内的提升
    • 跨作用域的提升
  • 函数提升
    • 函数声明语句能够实现提升
    • 函数表达式不进行提升
<script type="text/javascript">
//作用域内的提升
console.log(test);
var test=1;
//相当于
var test;
console.log(test);
test=1;

//跨作用域的提升
function say () {
    str="hello";
}
say();
console.log(str);
//相当于
var str;
function say () {
    str="hello";
}
say();
console.log(str);

//函数提升
go();
function go () {
    console.log('hello')
}
//相当于
function go () {
    console.log('hello')
}
go();
//函数表达式不会提升
to();
var to=function(){
    console.log('to');
}
</script>

闭包

  • JS没有块级作用域,容易导致很多问题
    • 规避冲突
      • 规避不同模块间变量的冲突
    • 避免污染
      • 避免污染全局变量
  • 闭包是指包含变量的函数,函数变量可以保存在函数作用域内。
  • 闭包是指有权访问上层函数作用域的内层函数
  • 闭包是指在函数声明时的作用域以外的地方被调用的函数

闭包

  • 闭包三个条件
    • 访问所在作用域
    • 函数嵌套
    • 在所在作用域外被调用
<script type="text/javascript">
function foo(){
    var a = 2;
    function bar(){
        console.log(a); //2
    }
    return bar;
}
foo()();
//简化为
function foo(){
    var a = 2;
    return function(){
        console.log(a);//2
    }
}
foo()();
</script>

闭包的用途

  • 可以读取函数内部的变量
  • 让这些变量的值始终保持在内存中

模拟块级作用域

<script type="text/javascript">
// 最常用的两种写法
(function(){ 
    /*代码*/
}()); 
//或者
(function(){ 
    /* 代码 */ 
})();
</script>

案例练习

单击测试

交互开发

旨为前端开发工程师的前端开发课程