JS面向对象之做用域

做用域

词法做用域

做用域

表示的就是范围,即做用范围java

  • 就是一个名字在什么地方能使用,在什么地方不能使用编程

    块级做用域

    级别的做用范围
// 在 c , java 等编程语言中,下面的语法报错
    {
        var num = 123;  // 应该用int , 这里是伪代码
        {
            console.log(num);   // 123
        }
        console.log(num);   // 报错
    }

在 js 中采起词法做用域

词法(代码)做用域,就是代码在编写过程当中体现出来的做用范围,代码一旦写好,不用执行,他的做用范围就已经肯定好了,这个就是所谓的词法做用域
在 js 中的词法做用域规则
1. 函数容许方位函数外的数据
2. 整个代码结构中只有函数能够限定做用域
3. 做用规则首先是提高规则分析
4. 就近原则若是当前做用规则有了名字,就不考虑外面的名字浏览器

在 js 中做用域分析方法

1. 先进行预解析,分析预解析过程
    * 程序在执行过程, 会先将代码读取到内存中检查. 会将全部的声明在此时进行标记. 所谓的标记就是
让 js 解释器知道有这个名字, 后面在使用名字的时候, 不会出现未定义的错误. 这个标记过程就是提高.
    * 声明
    1. 名字的声明, 标识符的声明( 变量名声明 )
        * 名字的声明就是让咱们的解释器知道有这个名字
        * 名字没有任何数据与之对应
    2. 函数的声明
        * 函数声明包含两部分
        * 函数声明与函数表达式有区别, 函数声明是单独写在一个结构中, 不存在任何语句, 逻辑判断等结构中
        * 首先函数声明告诉解释器有这个名字存在. 该阶段与名字声明同样
        * 告诉解释器, 这个名字对应的函数体是什么**(函数名和函数体绑定连接)**
2. 再进行代码执行过程

常见的简单做用域问题

例子 1:编程语言

var num = 123;
    function foo(){
        console.log(num);
    }
    foo();  // 输出 123

分析函数

  1. 预解析code

    变量num变量名提高
       函数foo函数名提高
  2. 代码执行内存

    num赋值123,函数内区域为独立区域,可使用外部数据,可是如今变量名相同,覆盖外面的值
       函数foo执行
       函数区域中变量num变量名提高
       输出num 为undefined
       num赋值456
       输出num 为456

例子 2:作用域

if(false){
        var num = 123;
    }
    console.log(num);   // 输出undefined

分析io

  1. 预解析console

    变量名num提高
  2. 执行代码

    if判断为false,不进入
       输出num,num定义未赋值,为undefined

例子 3:

var num = 123;
    function foo(){
        var num = 456;
        function fn(){
            console.log(num);   //  输出456
        };
        fn();
    }
    foo();

分析

  1. 预解析

    变量名num和函数名foo声明提高,函数名foo和函数体连接
  2. 执行代码

    num = 123, 赋值
       执行函数, 函数内部声明提高,变量名num和函数名fn
       变量num=456, 执行函数fn
       输出num, fn函数内部没有num,向上级寻找
       num=456, 输出num

例子 4:

var num = 123;
    function foo1(){
        var num = 456;
        function foo2(){
            num = 789;
            function foo3(){
                console.log(num);   // 输出789
            }
            foo3();
        }
        foo2();
    }
    foo1();     // 输出456
    console.log(num);   // 输出123

分析

  1. 预解析

    变量名num和函数名foo1声明提高,函数名foo1和函数体绑定
  2. 执行代码

    num = 123, 赋值
       执行函数foo1, 变量名num和函数名foo2声明提高, 函数名foo2和函数体绑定
       num = 456, 赋值
       执行函数foo2, num在foo2函数中没有, 访问上级foo1获得num,  num = 789, 赋值函数名foo3声明提高而且绑定函数体
       执行函数foo3, 输出num, foo3中没有num,访问上级,获得num = 789
       输出num为789
       跳出函数, 输出num为123

例子 5:

if ( ! 'a' in window ) {
        var a = 123;
    }
    console.log( a );   // undefined

分析

  1. 预解析

    变量a声明提高
  2. 执行代码

    判断window中是否存在a,a存在
       判断为false,不执行if中的代码
       输出a,为undefined

复杂的做用域问题

例子 1

if ( true ) {
        function f1 () {
            console.log( 'true' );
        }
    } else {
        function f1 () {
            console.log( 'false' );
        }
    }
    f1();

分析
新版浏览器

  1. 预解析

    无,函数f1被浏览器认为是函数表达式,不进行变量名提高
  2. 执行代码

    if判断进入true
       执行函数表达式f1
       输出结果为true

旧版浏览器

  1. 预解析

    函数f1变量声明提高,f1函数名和最后一个函数体链接在一块儿
  2. 执行代码

    if判断进入true
       执行f1
       输出false

例子 2

if ( false ) {
        function f1 () {
            console.log( 'true' );
        }
    } else {
        function f1 () {
            console.log( 'false' );
        }
    }
    f1();

分析
新版浏览器

  1. 预解析

    无,f1为函数表达式,没有进行声明提高
  2. 执行代码

    if判断
       执行f1
       输出false

旧版浏览器

  1. 预解析

    函数名f1,声明提高,函数名和最后一个函数体连接在一块儿
  2. 执行代码

    if判断
       执行f1
       输出false

例子 3

var num = 123;
    function f1() {
        console.log( num );
    }
    function f2() {
        var num = 456;
        f1();
    }
    f2();

分析

  1. 预解析

    声明提高,变量num,函数名f1,f2,函数名和函数体连接
  2. 执行代码

    num = 123
       执行函数f2
       变量num赋值456
       执行函数f1
       输出num,函数里面没有,向上寻找,上级为(0级做用域链),num=123,输出num为123

例子 4

var num = 123;
    function f1() {
        console.log( num );
    }
    function f2() {
        num = 456;
        f1(num);
    }
    f2();

分析

  1. 预解析

    变量名num,函数名f1,f2声明提高,函数名和函数体连接一块儿
  2. 代码执行

    num=123
     执行函数f2
     num=456,f2中没有num,向上级寻找获得num为123,将num = 123赋值,num = 456
     执行f1, f1中没有num, 向上级寻找获得num为456
     输出num,num=456,输出num456
相关文章
相关标签/搜索