作用域 {#作用域}

执行上下文

  1. console.log(a); // undefined
  2. var a = 100;
  3. fn('zhangsan') // 'zhangsan' 20
  4. function fn(name) {
  5. age = 20;
  6. console.log(name, age);
  7. var age;
  8. }
  • 范围:一段<script>或者一个函数
  • 全局:变量定义、函数声明
  • 函数:变量定义、函数声明、this、arguments
  • 注意⚠️“函数声明”和“函数表达式”的区别
  1. fn()
  2. function fn() {
  3. //声明
  4. }
  5. fn1()
  6. var fn1 = function () {
  7. //表示
  8. }
  9. var a = 100; //类似于这个
  10. //全局声明
  11. console.log(a);
  12. var a = 100;
  13. fn('zhangsan')
  14. function fn(name) {
  15. console.log(this);
  16. age = 20;
  17. console.log(name,age);
  18. var age;
  19. bar(100);
  20. function bar(num) {
  21. console.log(num);
  22. }
  23. }

作用域

  • 没有块级作用域
  • 只有函数和全局作用域
  1. //无块级作用域
  2. if(true){
  3. var name = 'zhangsan';
  4. }
  5. console.log(name);
  6. //函数和全局作用域
  7. var a = 100;
  8. function fn() {
  9. var a = 200;
  10. console.log('fn',a);
  11. }
  12. console.log('global',a);
  13. fn();

如何理解作用域

  • 自由变量
  • 作用域链,即自由变量的查找
  • 闭包的两个场景
  1. var x=10;
  2. function foo() {
  3. alert(x);
  4. }
  5. function bar() {
  6. var x=20;
  7. foo();
  8. }
  9. bar();
  • 生命周期
  • 作用范围

变量作用域

  • 静态作用域
  • 动态作用域

静态作用域

  • 被称为词法作用域
  • 由程序定义位置决定
  1. var x=10;
  2. function foo() {
  3. alert(x);
  4. }
  5. function bar() {
  6. var x=20;
  7. foo();
  8. }
  9. bar();

全局作用域
x 10
foo
bar

foo作用域
- -

bar作用域
x 20

动态作用域

  • 程序运行时刻
  • 栈操作

x:20
bar:
foo:

JS变量作用域

  • JS使用静态作用域
  • JS没有块级作用域(全局作用域、函数作用域)(ES5)
  • ES5中使用词法环境管理静态作用域
  1. var x = 10;
  2. function foo() {
  3. var z = 30;
  4. function bar(q) {
  5. return x + y + q;
  6. }
  7. return bar;
  8. }
  9. var bar = foo(20);
  10. bar(40);
  • 环境记录
    • 形式参数
    • 函数声明
    • 变量
  • 对外部词法环境的引用(outer)

  • 初始化

作用域 - 图1


  • 执行

作用域 - 图2


作用域链

  1. var a = 100;
  2. function fn() {
  3. var b = 200;
  4. //作用域没有定义变量,即“自由变量”
  5. console.log(a);
  6. console.log(b);
  7. }
  8. fn();
  9. var a = 100;
  10. function F1() {
  11. var b = 200;
  12. function F2() {
  13. var c = 300;
  14. console.log(a);//a是自由变量。形成一个链式结构,向父级去查找
  15. console.log(b);//b是自由变量
  16. console.log(c);//
  17. }
  18. }

对变量提升的理解

  • 变量定义
  • 函数声明(注意和函数表达式的区别)

创建10个<a>标签 点击的时候弹出来对应的序号

  • 错误写法
  1. //这是一个错误的写法!!!
  2. var i,a;
  3. for (var i = 0; i < 10; i++) {
  4. a = document.createElement('a');
  5. a.innerHTML = i + '<br>';
  6. a.addEventListener('click',function (e) {
  7. e.preventDefault();
  8. alert(i)
  9. })
  10. document.body.appendChild(a);
  11. }
  12. //输出为如下: <a>"9"<br></a>
  • 正确写法
  1. //这是一个正确写法!!!
  2. var i;
  3. for (i = 0; i < 10; i++) {
  4. (function(i){
  5. var a = document.createElement('a');
  6. a.innerHTML = i + '<br>';
  7. a.addEventListener('click',function (e) {
  8. e.preventDefault();
  9. alert(i);
  10. })
  11. document.body.appendChild(a);
  12. })(i)
  13. }