变量声明到底做了什么?

攻城狮
  • 3
新手上路,请多包涵

看了MDN说 JavaScript只会提升声明,不会提升其初始化,那么为什么声明一个未赋值的变量打印时的初始值是undefined?变量声明到底做了什么?

回复
阅读 496
7 个回答
✓ 已被采纳

声明就是取名,如果你没有声明很容易造成"误解",这个误解不仅是阅读代码的人,也是机器,
我们假设没有变量声明这种东西,也就是直接对一个变量赋值test=1;其实在非严格模式中你是可以省略变量声明(var/let/const)前缀的,它会直接挂在window上,所以这就会带来一个问题,如果我想一个变量也叫window呢?如果没有声明,那么你可能是想在一个函数中局部的使用这个名称,外部的window仍然是指全局的window,那这就会让人产生歧义,引擎也会理解成你是想对全局的window进行赋值,另一方面是,如果省略了变量声明,那么这个变量到底是在哪被声明的可能就很难查找。所以声明就像是取名,它标识了作用域内的一个内存地址的名称。
至于你说的未赋值的变量为什么是undefined,这个就是语言的规范,其他语言中也是,只不过不一定是undefined,它代表的就是未赋值的一种空状态

已参与了 SegmentFault 思否「问答」打卡,欢迎正在阅读的你也加入。

var foo = 'bar';

这里面 var foo 是声明,告诉内存我有一个变量需要存,内存会把变量的位置提供出来,位置里是空的,这时向内存要 foo,内存告诉你有一个叫 foo 的变量,但里面啥也没有,就是 undefined
foo = 'bar' 是变量的初始化,就是把 'bar' 这个值放到前面内存给的位置里。


如果申明都还没有,就向内存要 foo,内存就会找不到他,控制台这时会抛出异常:ReferenceError: foo is not defined

提升声明可以理解为提前占座,告诉内存这地我包了,后续这块地修鱼塘还是建大楼对内存来说还是未知的状态,所以就标记上个undefined

变量提升

比如说,你在平时coding是这样写的

function fn(){
  //...
}
var a = fn()

其实按照最原始的书写方式应该是这样的

var a
functio fn(){
  //...
}
a = fn()

那如果我们没有声明,直接赋值呢?

function fn(){
  //...
}
a = fn()

其实还是会自动给你在头部声明

var a
functio fn(){
  //...
}
a = fn()

但是,如果你是调用,就会报未找到,例如:

console.log(a)
// Error: Can't find variable: a
// 亦或
var b = {}
console.log(b.c)
// undefined

其实都是去寻找这个属性,比如a就是在当前点用的对象上去找a这个属性,简而言之就是 window.a 肯定没有嘛

只不过因为弱语言有一些规范没有那么强制罢了。


已参与了 SegmentFault 思否「问答」打卡,欢迎正在阅读的你也加入。

我的理解是主要理解 js解析机制就行。

遇到 script 标签的话 js 就进行预解析,将变量 var function 声明提升,但不会执行 function,然后就进入上下文执行,上下文执行还是执行预解析同样操作,直到没有 var function,就开始执行上下文。如:

a=5;
show();
var a;
function show(){};

预解析:

function show(){};
var a;
a=5;
show();

需要注意都是函数声明提升直接把整个函数提到执行环境的最顶端。

已参与了 SegmentFault 思否「问答」打卡,欢迎正在阅读的你也加入。

堆主要存储普通的变量,容量比较小。栈存储引用型变量,空间很大。比如对象、数组、函数。
例如:

var fun;
console.log(fun);
function fun(){
console.log('222');
}

上面会先在堆上创建一个 var fun。输出:undefined,

代码执行到fun()会从堆上查找,找到 var fun,但发现没有被赋值,就回去栈上找,最终输出222
已声明但是没有初始化的变量的值为undefined.

可以理解为,变量分为三个过程,声明,初始化,赋值;
var 声明的时候,同时进行了初始化,在栈中分配一个空间,此时没有赋值,值就是undefined;
function 作为javascript 中的一等公民,在执行之前,也就是预编译阶段,会将function 声明提到作用域顶部,其次的var声明的变量;

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏