var和function声明提升的区别

文章详细解释了JavaScript中的声明提升现象,包括变量和函数声明的提升规则。它指出,只有声明部分会被提升,赋值操作仍然保持原位。函数声明会优先于变量声明提升。文章通过多个代码示例展示了这种提升如何影响代码执行,特别是函数声明与函数表达式的区别,以及在不同作用域内的行为。最后,文章提供了两个面试题来测试读者对这一概念的理解。
摘要由CSDN通过智能技术生成

问题的提出

我们先来看两段代码,猜猜会输出什么?

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

正确输出分别是2undefined
为什么会这样呢?这里就涉及到JavaScript的声明提升。

什么是声明提升

包括变量的和函数在内的所有声明都会在任何代码执行前首先被处理。

注意,只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。如果提升改变了代码执行的顺序,会造成非常严重的破坏。

当你看到var a = 2时,可能会认为这是一个声明,但JavaScript实际上会将其看出两个声明var a;a = 2;。第一个定义声明是在编译阶段进行的。第二个赋值声明会被留在原地等待执行阶段。

所以上面的第一个代码片段会以如下形式进行处理:

var a 
a = 2
console.log(a)

第二个代码片段:

var a
console.log(a)
a = 2

再来看两个片段:

foo()
function foo() {
  console.log('foo')
}
foo()
var foo = function() {
  console.log('foo')
}

第一个代码片段会正常输出foo
第二个代码片段,报错:Uncaught TypeError: foo is not a function

函数声明会被提升,但是函数表达式却不会被提升。

var和function分别定义函数的区别

代码片段1:

var foo = function () {
  console.log("foo -- var");
};
function foo() {
  console.log("foo -- function");
}
foo();

分析代码执行如何执行的?

  1. 首先遇到var声明
var foo = function () {
  console.log("foo -- var");
};

变成:

var foo
foo = function () {
  console.log("foo -- var");
};
  1. 接着看到函数声明,会提升
function foo() {
  console.log("foo -- function");
}

变成:

var foo
function foo() {
  console.log("foo -- function");
}
foo = function () {
  console.log("foo -- var");
};
  1. 所以上面代码片段实际代码执行:
var foo
function foo() {
  console.log("foo -- function");
}
foo = function () {
  console.log("foo -- var");
};
foo();

所以输出:foo – var

代码片段2:

console.log(a);
if (false) {
  var a = 1;
}

当使用 var 声明变量时,它写在哪里都是一样的,因为它们最终都会函数作用域和块作用域 属于外部作用域。
所以 上面代码片段输出undefined,而不是报错。

代码片段3:

var foo = 2;
function foo() {}
console.log(typeof foo);

结果输出number
分析结果:

var foo;
function foo() {}
foo = 2;
console.log(typeof foo);

foo = 2,所以输出number

函数优先

函数声明和变量声明都会被提升。但是一个值得注意的细节是函数会首先被提升,然后才是变量。

foo(); // 1
var foo;
function foo() {
  console.log(1);
}
foo = function () {
  console.log(2);
};
foo(); // "b"
var a = true;
if (a) {
  function foo() { console.log("a"); }
}
else {
  function foo() { console.log("b"); }
}

面试题分析

题目1

代码片段如下,给出正确的输出结果

var foo = function () {
  console.log("foo1");
};
foo();

var foo = function () {
  console.log("foo2");
};
foo();

function foo() {
  console.log("foo1");
}
foo();

function foo() {
  console.log("foo2");
}
foo();

经分析,实际执行如下:

var foo
function foo() {
  console.log("foo1");
}
function foo() {
  console.log("foo2");
}
foo = function () {
  console.log("foo1");
};
foo()
foo = function () {
  console.log("foo2");
};
foo();
foo();
foo();

正确输出如下:
foo1foo2foo2foo2

题目2

代码片段如下:

var a = 0;
console.log("第一次输出a: ", a);
if (true) {
  a = 1;
  console.log("第二次输出a: ", a);
  function a() {}
  a = 2;
  console.log("第三次输出a: ", a);
}
console.log("第四次输出a: ", a);

分析如下:

var a = 0 // 外部a
console.log("第一次输出a: ", a) //输出外部a
if (true) {
    // 这里js隐式的把function a的定义放到这里来了,此刻这里有一个内部a
    a = 1 // 将内部a由函数修改为1
    console.log("第二次输出a: ",a) // 此时输出的是内部a
    function a() {} // 执行到function a的声明处,此时会将if块中的a提升到外部去,也就是把内部a赋值给了外部a, 外部a此刻被修改了
    a = 2 // 此处修改的是内部a, 内部a被由1修改为2
    console.log("第三次输出a: ", a) // 输出内部a 也就是a
}
console.log("第四次输出a: ",a) // 输出外部a,由于if块中的声明同步,将外部a从0同步成了1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值