Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS 作用域链相关问题 #25

Open
jirengu opened this issue Jan 3, 2017 · 5 comments
Open

JS 作用域链相关问题 #25

jirengu opened this issue Jan 3, 2017 · 5 comments

Comments

@jirengu
Copy link
Owner

jirengu commented Jan 3, 2017

最近讲到作用域链,再来一发作用域链的题目。下面代码输出什么? 为什么?

var a = 1;

function fn(){
  console.log(a); 
  var a = 5;
  console.log(a);  
  a++;
  var a;
  fn3();
  fn2();
  console.log(a);

  function fn2(){
    console.log(a); 
    a = 20;
  }
}

function fn3(){
  console.log(a)
  a = 200;
}

fn();
console.log(a); 
@RookieDay
Copy link

下面是我的理解,有什么问题还望指正,解法采用和 #23 一样的解法。

  • 首先贴图,接下来解释,看图做题一目了然, 图上数字依次标出console.log的地方
    untitled
  • 绘制作用域链原则
    1. 先画一条主链条 暂且叫做0级别
    2. 有一个fn就引出一条新的作用域链级别 叫做1级别, 依次累加2级别、3级别.....
  • 解释
fn();
console.log(a); 
  1. 首先是执行fn, 根据绘制的作用域链,进入1级别
    第一次 console.log(a) --> 1级别上从此处开始往上找,可以发现a尚未赋值 所以输出undefined
    第二次 console.log(a)---> 1级别上从此处开始往上找,可以发现a已经赋值5,所以输出5 ,后面a++以后a的值变为6
    接下来执行fn3() --> 第三次console.log(a) 此时fn3()是在0级别上, 从此处开始往前找,a 为1 ,所以输出 1,之后a=200, 0级别a被重新赋值,从1变成200
    接下来执行fn2() --> 第四次console.log(a) 此时fn2()是在2级别上, 从此处开始往前找,因为1级别上a自增了,所以此处输出 6,之后a=20, 1级别上的a被重新赋值为20
    第五次执行console.log(a)-->1级别上, 因为在上一步a的值已经被重新赋值为20,所以此处输出 20
  2. 接下来是执行console.log(a)
    console.log(a) 是在0级别上,如图标号6 所以此处输出 200
  3. 结果
undefined
5
1
6
20
200

@FrankFang FrankFang changed the title JS-作用域链相关问题 JS 作用域链相关问题 Jan 11, 2017
@mydaoyuan
Copy link

作用域链是定死的,函数引用的变量在哪里定义,引用的就是哪里的变量.

fn3()在全局定义,所以引用的是全局的a

fn2在fn内部定义,fn内部有一个a了,所以fn2操作的都是fn内的a,

第一个undefined是因为var声明变量提前所以是undefined.

@n313893254
Copy link

window {
    a: 200,
    fn {
        a:20
        fn2 {
            
        }
    }
    fn3 {
        
    }
}

@zx562602419
Copy link

zx562602419 commented Apr 27, 2017

最终输出为:

undefined
5
1
6
20
200

答案分析:

var a = 1;
function fn(){
  console.log(a);        //第一个输出值        ---->  undefined
  var a = 5;
  console.log(a);        //第二个输出值        ---->  5  
  a++;
  var a;
  fn3();
  fn2();
  console.log(a);       //第五个输出值          ---->  20

  function fn2(){
    console.log(a);     //第四个输出值          ---->   6
    a = 20;
  }
}

function fn3(){
  console.log(a)       //第三个输出值      ---->  1
  a = 200;
}

fn();
console.log(a);       //第六个输出值        ---->  200

1、作用域在全局,调用全局变量 a,但由于函数内部变量重新声明,且根据变量声明提前但赋值不会提前,所以输出 undefined
2、作用域在函数 fn 内,调用 fn 内变量 a,此时函数内变量声明且赋值 var a = 5,所以输出为 5
3、作用域在全局,此时调用全局变量 a, 所以输出为 1
4、作用域在 fn 内,调用 fn 内变量 a,此时 fn 内由 a++ 计算后,a = 6,所以输出为 6
5、作用域在 fn 内,调用 fn 内变量 a,此时由于 fn2 函数执行,fn 内变量 a 重新赋值为 a = 20 ,所以输出为 20
6、作用域在全局,调用全局变量 a,此时由于 fn3 函数执行,全局变量 a 重新赋值为 a = 200 ,所以输出为 200

@ibufu
Copy link

ibufu commented Jul 18, 2017

变量声明提前
function的作用域在声明处定义

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants