发新贴  快速回复

js作用域的问题

李天赐
2015-11-22 11:13
 本帖最后由 谦谦君子2015 于 2015-11-22 11:14 编辑 

昨天听了刘伟老师讲解js作用域的问题,讲的非常精彩。我听了后,感觉对作用域的都掌握了。今天到网上看看一些别人写的博客,上面的列子也都能懂,但是刚才看到一个问题,用老师的将的知识没有能理解,在这里希望得到帮助。

昨天刘伟老师说,在浏览器对代码逐行执行前,会先执行预解析代码,在这个过程中,会在js域中找到var、function、参数这三样东西。var定义的变量,就保存名称,并且赋值给undefined,function声明的函数就将这个函数体放在内存库中;参数就当局部变量一样处理,放在对应的作用域的仓库中。预解析完成后,就进行逐行执行代码,代码中访问的变量,都到预解析时候存的仓库中去访问。

比如如下代码:     var b = 2;
        function a() {
            alert(b);
            var b = 1;
        }
        a();
        alert(b);
   

用上面说的原则,浏览器先对代码预加载,找到var b,放到js仓库中,赋值undefined,找到函数a,将整函数体放到仓库中,然后逐行执行代码。var b=2的时候,更改了仓库中b的值(表达式可以更改预加载的值),b=2;然后方法,因为没有调用,所以直接过了。然后执行a();调用方法,又会执行预加载。找到域中的b,赋值undefined,然后没有任何var 和fucntion和参数了,继续逐行执行代码。alert(b);的时候,弹出仓库中b的值undefined,然后执行下面的b=1;此时更改的是局部域中的b。和外面定义的b没有关系。最后执行外面的alert(b)的时候,弹出的是2.

感觉按照刘伟老师的解释,一切都能把问题解决,然后我又看到这样子的一个代码。。。解释就不通了。。
    function t() {
         s = "ifscope";
     }
    t();
   console.log(s);

不理解的是为什么没有报错!!
首先js预加载,找到一个函数t。放到仓库中,然后没有了。然后就调用t函数,然后在函数里面预加载,没有找到任何东西。然后逐行执行代码。执行s=isscoped的时候,会到仓库中找s。但是根本没有找到。为什么给赋值的时候没有报错呢????


网上找资料说,没有用var定义的就是全局的。。。。。





 
创美易-miaov
如果不带var声明,s是全部window的属性,window.s = xxxx;
2015-11-22 11:58  回复本帖
李天赐
forum.php?mod=redirect&goto=findpost&pid=44026&ptid=14843
如果不带var声明,s是全部window的属性,window.s = xxxx;

那假如直接 :<script>
console.log(a);

</script>

会报错,那这个不带var的变量申明,不会进行预加载么?
2015-11-22 14:03  回复本帖
 
创美易-miaov
forum.php?mod=redirect&goto=findpost&pid=44029&ptid=14843
那假如直接 :
console.log(a);



报错是因为没有定义
2015-11-22 15:15  回复本帖
李天赐
forum.php?mod=redirect&goto=findpost&pid=44030&ptid=14843
报错是因为没有定义

直接访问的时候报错,是因为没有定义。那直接赋值的时候,不也是没有定义么?怎么就没有报错呢?
2015-11-22 19:58  回复本帖
 
创美易-miaov
forum.php?mod=redirect&goto=findpost&pid=44031&ptid=14843
直接访问的时候报错,是因为没有定义。那直接赋值的时候,不也是没有定义么?怎么就没有报错呢?
 ...

1.
window.s;
function t() {
         window.s = "ifscope";
     }
    t();
   console.log(window.s);


直接赋值,本质是这样,js会自动定义了window.s,这个我们是看不到的,摸不着的, 然后在t函数里面初始化,cosole出来就是ifscope;


2.
<script>
cosole.log(s)
</script>
因为没有定义这个s,这个s真的不存在,所以报错。
建议你好好去看一下视频。


2015-11-22 22:30  回复本帖
李天赐

我理解的
<script>
    var a=1;
    console.log(a);
  
     1.预加载:
       1.1、找到var定义的a,存储到运行环境中,并且赋值为Undefined
     2.逐行执行代码
       2.1、执行到var a=1时,到运行环境中取出预加载定义的a,并执行表达式把结果赋值给a。此时运行环境中的a的值为1;
       2.2、执行到console.log(a)时候,到运行环境中找到a,并且取出值1后输出。   
     注:这个过程没有疑惑,但是不知道我这样理解的算不算正确的。

</script>

我不理解的
<script>
    b=1;
    console.log(b);
  
     1.预加载:
       1.1、没有找到任何var定义的变量,运行环境中为空。
     2.逐行执行代码
       2.1、执行到b=1时,去运行环境中去找b,但是没有找到;*没有报错!
       2.2、执行到console.log(b)时候,到运行环境中找到b,并且取出值输出。*这个时候运行环境中并没有b
   
    我不理解的地方:
     1、预解析的时候没有找到变量b,但是没有报错!
     2、如果说,逐行执行的时候,操作一个没有定义的变量的,系统会自动创建一个全局的变量的话
        那下面代码为什么又会报错了。。。。。。。。。
</script>

<script>
    a    //只是“声明”,不进行操作。 我理解的:没有定义,系统自动声明,声明一个变量不会报错。
    console.log(b); // 和“b=1”表达式一样,不定义,直接访问。系统自动声明的话,直接输出声明后的默认值。
    c=c+c; // 自己操作自己。

</script>

2015-11-23 12:41  回复本帖
 
leo
forum.php?mod=redirect&goto=findpost&pid=44047&ptid=14843


b=1;
console.log(b);

1.预加载:
    1.1、没有找到任何var定义的变量,运行环境中为空。
2.逐行执行代码
    2.1、执行到b=1时,去运行环境中去找b,但是没有找到;
    由于这是赋值语句,因此程序会帮你创建一个全局变量var b,并赋值为1。
    2.2、执行到console.log(b)时候,到运行环境中找到b,并且取出值输出。

2015-11-23 16:29  回复本帖
 
leo
forum.php?mod=redirect&goto=findpost&pid=44047&ptid=14843


<script type="text/javascript">
    a;
    alert(a);
</script>

如果只是单独写了一个a,程序肯定会在a这一行就报错,因为预解析中没有a,也不是赋值,程序不知道这个a是什么意思,会认为你语法错误,就会在这一行中断你的整个程序,也就根本读不到alert(a);这一行了。

2015-11-23 16:33  回复本帖
Jimmzy
为什么会报错,在函数中未加var就是全局变量,函数体内的s是全局变量!
2015-11-26 18:14  回复本帖
Jimmzy
 本帖最后由 Jimmzy 于 2015-11-26 19:59 编辑 

全局下访问a,会报错
2015-11-26 18:16  回复本帖
 
创美易-miaov
forum.php?mod=redirect&goto=findpost&pid=44142&ptid=14843
为什么会报错,在函数中未加var就是全局变量,函数体内的s是全局变量!

这是js语法明码规定的,声明一个变量必须用var,
如果不初始化就是undefined类型,
如果不带var定义了变量,必须要初始化,
如果不带var定义了变量,也没有初始化就会报错,


说的通俗一点:打个比方==》你妈妈生你出来之后,她会给你起名字上户口你就有身份的人,不然你就是黑户口,黑户口会被查会被阿sir抓去。

2015-11-26 21:01  回复本帖
登录 后才可以发表回复