JavaScript中的变量

来源:互联网 发布:淘宝上衣服的来源 编辑:程序博客网 时间:2024/05/27 00:28

懂点编程的都知道,执行环境的类型总共只有两种:全局和局部

var color ="blue";function changeColor() {    var num =10;    console.log(num);console.log(color);}changeColor();console.log(num);

在这个例子中,color是全局变量,num是局部变量,color能被函数内部访问,但是num不能被外部访问。因此会输出 10 blue 第三句会报错 num is not defined。

我们再来看例子分析 从例子中发现问题,引出原理,解决问题。

var num = 10;function changeNum() {    console.log(num);}changeNum(); 

毫无疑问,一定输出 10 。函数执行的过程你知道吗?
当执行函数changeNum()的时候,先在函数体内部查找是否有变量num 的声明,如果没有,就往外层去找。本例子中,函数体内部并没有var声明的变量num,因此会找到函数体外面的num。因此最后会输出10。
再来看一个例子

var num = 10;function changeNum() {    console.log(num);    var num = 9;    console.log(num);}changeNum();

在本例子,你猜结果会输出什么?
第一个输出undefined
第二个输出 9
为什么会这样呢? 先来看函数的执行过程,因为要输出num,先来查看函数体内部是否有var 声明的变量num,结果发现,在函数体内第二行有个var num =9;也就是找到了变量num的var声明,这个时候函数是不会再往外层去寻找num了,会把当前的num声明放在函数体内的最顶端,即var num;但是不赋值,故输出undefined。此时,var num =9;也就变成了num=9;故第二个输出会输出9.
上面的例子就是如下:

var num =10;function changeNum() {    // 先声明变量num;    var num;    console.log(num); // undefined    // 再赋值     num = 9;    console.log(num);// 9}

函数变量的提升,我在这篇博客javascript变量知识小梳理中有提到过。
因此在这里再啰嗦一遍:
如果在函数体内有变量声明,会将此变量的声明放在函数体内最顶端,只是声明(如var num;),并不赋值。
其实这是js中作用域的问题

深度剖析:
Js中的作用域分析,作用域其实就是起作用的范围。在js中唯一能产生作用域的东西就是函数了,js中没有块级作用域(这个稍后讲解)
• Js中程序在执行中,会先进行一个预解析,分析预解析的过程,即:
 程序在执行过程, 会先将代码读取到内存中检查. 会将所有的声明在此时进行标记. 所谓的标记就是让 js 解释器知道有这个名字, 后面在使用名字的时候, 不会出现未定义的错误. 这个标记过程就是提升.
 声明
变量的声明, 标识符的声明
变量的声明就是让我们的解释器知道有这个名字
变量没有任何数据与之对应,即不先给其赋值
函数的声明
函数声明包含两部分
函数声明与函数表达式有区别, 函数声明是单独写在一个结构中, 不存在任何语句, 逻辑判断等结构中
首先函数声明告诉解释器有这个名字存在. 该阶段与名字声明一样
告诉解释器, 这个名字对应的函数体是什么(函数名和函数体绑定链接)
• 再进行代码执行过程

知道这些,所以变量的提升并不难理解了吧!
刚才有提到函数没有块级作用域的问题,这是什么意思呢?
先上代码,看看

if (true){    var num = 8;}console.log(num);

你猜会num会输出什么? 答案是8.
这里再一个if语句中定义了变量num。如果是在C C++ 或Java中,num会在if语句执行完毕后被销毁。但在JavaScript中,if语句的变量声明会将变量添加到当前的执行环境中(这里是全局环境)中。因此会输出8。在使用for语句时,尤其要牢记这一点。看例子:

for(var i =0;i<10;i++) {   var str = "你猜会输出什么";}console.log(i);

由于js没有块级作用域,由for语句创建的变量i即使在for循环执行结束后,也依旧会存在于循环外部的执行环境中。所以最后会输出10.

来看牛客网上一道题

现有如下html结构    <ul> <li>click me</li> <li>click me</li> <li>click me</li> <li>click me</li></ul>运行如下代码:        var elements=document.getElementsByTagName('li');    var length=elements.length;    for(var i=0;i<length;i++){        elements[i].onclick=function(){        alert(i);    } }依次点击4li标签,哪一个选项是正确的运行结果()?结果依次弹出  4 4 4 4

Js的块级作用域现在ES6中已经有了定义,其实用闭包也可以实现
ES6的块级作用域:用let为JavaScript新增了块级作用域

for(let i =0;i<10;i++) {   var str = "你猜会输出什么";}console.log(i);结果会报错 i is not defined
原创粉丝点击