锁定老帖子 主题:关于js解析执行有趣的事
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-06-18
最后修改:2012-06-18
前些天总监在群里发了两段代码:
var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar();
var a = 1; function b() { a = 10; return; function a() {} } b(); alert(a); 不测试,大家看输出的是什么? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-06-18
第一题
10 第二题 1(局部和全局变量不同) |
|
返回顶楼 | |
发表时间:2012-06-18
xleon 写道 第一题
10 第二题 1(局部和全局变量不同) 这答案没说服力啊 |
|
返回顶楼 | |
发表时间:2012-06-18
liukemin 写道 xleon 写道 第一题
10 第二题 1(局部和全局变量不同) 这答案没说服力啊 楼上说的没有错,想简单理解的话,可以想象在第一个例子的函数bar进入时候第一行加一行 var foo = undefined 在第二个例子的函数b的第一行加一个 var a = undefined 解析作用域时候,该作用域里面不管哪行定义了东西,都可以简单想象成第一行声明了一个未初始化的同名变量。 (纯粹为了容易理解) |
|
返回顶楼 | |
发表时间:2012-06-18
red008 写道 liukemin 写道 xleon 写道 第一题
10 第二题 1(局部和全局变量不同) 这答案没说服力啊 楼上说的没有错,想简单理解的话,可以想象在第一个例子的函数bar进入时候第一行加一行 var foo = undefined 在第二个例子的函数b的第一行加一个 var a = undefined 解析作用域时候,该作用域里面不管哪行定义了东西,都可以简单想象成第一行声明了一个未初始化的同名变量。 (纯粹为了容易理解) 这关系到JS解析顺序的问题,当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。 做如下处理: 1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。 2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined) 换个角度来说,这个是函数体升迁的问题,如果是用 var fn = function() 这种形式来定义,那么 fn 会升迁,但是函数体不会升迁,因此会报告错误说 fn 不是一个方法(注意不是报告未定义),而如果使用 function fn() 来定义方法,那么 fn 和函数体会同时升迁,这样 fn() 是可以调用到结果的。 |
|
返回顶楼 | |
发表时间:2012-06-18
red008 写道
liukemin 写道 xleon 写道 第一题 10 第二题 1(局部和全局变量不同) 这答案没说服力啊 楼上说的没有错,想简单理解的话,可以想象在第一个例子的函数bar进入时候第一行加一行 var foo = undefined 在第二个例子的函数b的第一行加一个 var a = undefined 解析作用域时候,该作用域里面不管哪行定义了东西,都可以简单想象成第一行声明了一个未初始化的同名变量。 (纯粹为了容易理解) 这关系到JS解析顺序的问题,当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。 做如下处理: 1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。 2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined) 换个角度来说,这个是函数体升迁的问题,如果是用 var fn = function() 这种形式来定义,那么 fn 会升迁,但是函数体不会升迁,因此会报告错误说 fn 不是一个方法(注意不是报告未定义),而如果使用 function fn() 来定义方法,那么 fn 和函数体会同时升迁,这样 fn() 是可以调用到结果的。 不怎么懂 |
|
返回顶楼 | |
发表时间:2012-06-19
不理解,有没有相关知识的书或文章可以参考一下的
|
|
返回顶楼 | |
发表时间:2012-06-19
有意思,以前只以为会自动向上一级域寻找定义,原来只是赋值的时候。学习了。
|
|
返回顶楼 | |
发表时间:2012-06-19
最后修改:2012-06-19
liukemin 写道 red008 写道 liukemin 写道 xleon 写道 第一题
10 第二题 1(局部和全局变量不同) 这答案没说服力啊 楼上说的没有错,想简单理解的话,可以想象在第一个例子的函数bar进入时候第一行加一行 var foo = undefined 在第二个例子的函数b的第一行加一个 var a = undefined 解析作用域时候,该作用域里面不管哪行定义了东西,都可以简单想象成第一行声明了一个未初始化的同名变量。 (纯粹为了容易理解) 这关系到JS解析顺序的问题,当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。 做如下处理: 1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。 2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined) 换个角度来说,这个是函数体升迁的问题,如果是用 var fn = function() 这种形式来定义,那么 fn 会升迁,但是函数体不会升迁,因此会报告错误说 fn 不是一个方法(注意不是报告未定义),而如果使用 function fn() 来定义方法,那么 fn 和函数体会同时升迁,这样 fn() 是可以调用到结果的。 一团,看懂一部分又有新的看不懂,感觉是解释的太多又没说详细,比如 “活动对象”,“该执行环境的拥有者”是什么,“升迁”。会给人越看问题越多的感觉。 个人的简单理解是不管是var c,还是 function c(){}都定义了一个变量c.而javascript变量定义是整个scope的,所以在一开始就有一个undefined的c变量隐藏了outer scope的c。 另外则是: function c(){} 和 var c = function(){}的不同是第一个作为函数在整个scope都有效,而第二个则只有变量c在整个scope有效.而为什么有这种区别对待,也和两者语义有关,第二个变量上面已经提过(个人觉得javascript这么设置并不合理,局部变量顺序定义更容易观察和理解)。第一个则接近于方法,方法自然不应为其定义顺序影响. 和 javascript是没有if block这种scope的,所以if里面的和函数内部其实是同一个scope.记得javascript只有函数才有scope. ---------------- 变量一开始就声明了但没赋值和一开始就没声明变量的区别是,一个是undefined,一个会报reference错误. |
|
返回顶楼 | |
发表时间:2012-06-19
最后修改:2012-06-19
不明白为什么第二个例子去掉function a() {}就能赋值了,后面那个函数是干吗用的,不是之前已经return了吗?
|
|
返回顶楼 | |