var foo = 'bar';
这里面 var foo
是声明,告诉内存我有一个变量需要存,内存会把变量的位置提供出来,位置里是空的,这时向内存要 foo
,内存告诉你有一个叫 foo
的变量,但里面啥也没有,就是 undefined
;foo = 'bar'
是变量的初始化,就是把 'bar'
这个值放到前面内存给的位置里。
如果申明都还没有,就向内存要 foo
,内存就会找不到他,控制台这时会抛出异常:ReferenceError: foo is not defined
。
比如说,你在平时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声明的变量;
10 回答11.2k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答5.1k 阅读✓ 已解决
3 回答1.9k 阅读✓ 已解决
声明就是取名,如果你没有声明很容易造成"误解",这个误解不仅是阅读代码的人,也是机器,
我们假设没有变量声明这种东西,也就是直接对一个变量赋值
test=1
;其实在非严格模式中你是可以省略变量声明(var/let/const
)前缀的,它会直接挂在window
上,所以这就会带来一个问题,如果我想一个变量也叫window
呢?如果没有声明,那么你可能是想在一个函数中局部的使用这个名称,外部的window
仍然是指全局的window
,那这就会让人产生歧义,引擎也会理解成你是想对全局的window
进行赋值,另一方面是,如果省略了变量声明,那么这个变量到底是在哪被声明的可能就很难查找。所以声明就像是取名,它标识了作用域内的一个内存地址的名称。至于你说的未赋值的变量为什么是
undefined
,这个就是语言的规范,其他语言中也是,只不过不一定是undefined
,它代表的就是未赋值的一种空状态