JS申明变量之前先console它不会报错是为什么?

有一次去面试的时候,遇到这么一个看上去非常简单明了的题目,但答案却又不明觉厉!

console.log(a);
console.log(f);
var a = 2;
function f(a){
  a = 3;
}
f(a);
console.log(a);
console.log(f);

乍一看很明了,“简单”的我都怀疑自己的答案了,然而确实不用怀疑,自己的答案就是错的!正确的输出结果是这样的:

console.log(a); //undefined
console.log(f); //f(a){a = 3}
var a = 2;
function f(a){
  a = 3;
}
f(a);
console.log(a); //2
console.log(f); //f(a){a = 3}

那就一行一行的解释以下

  • 第一行:“a”没有声明为什么不报错?

原来JS有一个变量声明提前的机制,var 定义变量的时候,js是首先直接把变量声明到作用域的最顶部的,所以这个时候,全局都能找到这个变量,所以在定义之前调用这个变量,是不会报错的。

下面左右两边的代码是完全一样:

console.log(a);                    var a;
                        ===        console.log(a);
var a = 2;                         a = 2;   

当然这只局限于var声明,如果用let声明就不行了,就会报错!

  • 接着第二行为什么函数f()没有声明却还能输出值?

与变量声明提前一样,函数也有个神经机制,就是函数声明提前,但与变量不一样的是,函数提前的是函数体,也就是说,在作用于范围内,只有又函数,不管函数体写在哪儿,同意上升到作用域最顶端!

上代码,左右两边全等于

console.log(f);                     function f(a){
function f(a){         ===             a = 2;
  a = 2;                            }
}                                   console.log(f);
  • 第三次输出为什么a的值没有改变?

因为JS的函数是值传递,上述代码并没有把"a"这个变量传到函数中,而是把"2"这个值传过去了,所以函数中如何对这个值修改都不会影响到变量"a"

  • 如果用同一个变量名来声明函数和变量,该是什么情况?
console.log(a);
var a = 2;
function a(){
console.log("bazinga");
}

这里又要说到JS的另一个规定,函数会首先被提升,然后才是变量。也就是说,同一作用域下提前,函数会在更前面。以上代等同于:

function a(){
  console.log("bazinga"); // bazinga
}
var a; //重复声明且未改变对象值,这一行直接被忽略
console.log(a); //输出函数体
a = 2;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。