这篇文章发布于 2010年10月14日,星期四,21:34,归类于 外文翻译。 阅读 54227 次, 今日 3 次 7 条评论
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=1162
前两天我又一次看了玉伯的JavaScript运行机制浅探,以加深自己对JavaScript运行原理方面的一些理解。恰好,今天见到一篇国外的文章,就是关于“预解析”的,还有视频内容,于是决定翻译下,对自己而言算是进一步的梳理与加深认识,以下就是翻译的全部内容,为了语言的生动以及本土化要求,内容可能有所编辑。
//zxx:以下为翻译全部内容
一、根正苗红的引子
今天这个视频诞生的原因是由于回答twitter上的一个关于JavaScript“预解析”的问题。//zxx:原单词为”hoisting”,我翻译成了“预解析”,若有不准,欢迎指正。
那么什么是“预解析”?它是如何工作的?你需要知道它的那些小秘密呢?所有这些问题的回答可以从下面这个比较基础的视频教程中找到。
二、“预解析”解释
考虑下面的代码:
var myvar = 'my value';
alert(myvar); // my value
Okay, 当然,弹出的结果肯定是"my value"
,但是,跟着我,让我下面创建个方法,弹出相同的值:
var myvar = 'my value';
(function() {
alert(myvar); // my value
})();
好吧,好吧,仍然很明显,我知道。现在,让我们加点猛的调料,在匿名函数内部创建一个同名的局部变量。
var myvar = 'my value';
(function() {
alert(myvar); // undefined
var myvar = 'local value';
})();
哈啊?为什么弹出的是undefined
呢?即使我们声明了一个新的变量,但是它在alert的下面啊,照理说应该不会有影响啊,是吗?还是?
三、变量声明被“预解析”
在当前的作用域内,无论在哪里变量声明,在幕后,其都在顶部被“预解析”了。不过,仅声明被“预解析”。该变量即使初始化,其当前的值,在作用域的顶部,也会被设置成undefined
。
恩,现在让我们好好的破译下这个“声明”和“初始化”,以var joe = 'plumber';
为模特吧。
声明(Declaration)
var joe; // the declaration
初始化(Initialization)
joe = 'plumber'; // the initialization
现在,我们知道了这些术语的意思,就可以更好的理解到底背地里都干了些什么勾当,请看下面的伪函数:
(function() { var a = 'a'; // 一行代码 var b = 'b'; // 更多行的代码 var c= 'c'; // antipattern // 最后一行脚本 })();
需注意,上面的这做法是不太好的。但是,先不管这个,在程序的背后,这个变量声明无论在函数作用域的什么地方,都被置顶解析了,就像下面这样:
(function() { var a, b, c; // variables declared a = 'a'; // 一行代码 b = 'b'; // initialized // 更多行的代码 c= 'c'; // initialized // 最后一行脚本 })();
四、soga!
现在回到令人疑惑的undefined
代码段
var myvar = 'my value';
(function() {
alert(myvar); // undefined
var myvar = 'local value';
})();
现在应该比较容易理解为何myvar
弹出的是undefined
了。正如上面学到了,当我们声明myvar
变量的时候,其自动的在函数作用域的顶部(在alert的前面)进行“解析”了。结果,在alert的时候时的变量还没有被声明。然而,由于初始化的值是不会作用域置顶的,所以,最后alert的值是undefined
。
//zxx:以上为翻译全文
译者补充:
上面弹出undefined
的代码实际上就等效于下面的代码:
var myvar = 'my value';
(function() {
var myvar;
alert(myvar); // undefined
myvar = 'local value';
})();
JavaScript的预解析不仅适用于变量,似乎也适用于函数,你有兴趣可以看下下面这个例子:
g = function() { return false; };
(function() {
if(g()) {
function g() { return true; }
alert("in"); //IE6~8,Chrome,Safari,Opera浏览器执行
}
})();
在非Firefox浏览器下,会弹出字符串"in"
的,当然,这里的重点不是哪个浏览器执不执行,所以不考虑Firefox的问题,function g() { return true; }
含函数作用域顶部(在if的前面)“预解析”,所以,if语句可以执行。
本文涉及到JavaScript一些运行机制,本身资质也有限,所以文章可能有翻译或是表述不准确的地方,还望不遗余力的指正,不甚感谢。
本文为原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=1162
(本篇完)
- 我是如何理解"Another JavaScript quiz"中的题目 (0.678)
- 翻译-高质量JavaScript代码书写基本要点 (0.486)
- 翻编-JavaScript有关的10个怪癖和秘密 (0.321)
- CSS @scope他来了 (0.190)
- JS中的柯里化(currying) (0.119)
- 小折腾:JavaScript与元素间的抛物线轨迹运动 (0.119)
- 如何使用Tween.js各类原生动画运动缓动算法 (0.119)
- canvas 2D炫酷动效的实现套路和需要的技术积累 (0.119)
- 深入 JS new Function 语法 (0.119)
- 小tips:了解CSS变量var (0.106)
- 应运而生的web页面响应布局 (RANDOM - 0.013)
哈哈哈,跟着大佬走,以前向您学习CSS(还买过几本书,受益颇多),现在向你学习JS
我搜浏览器渲染机制的预解析,竟然进入css大神这里了,这个是变量提升,创建执行上下文时候,会先生成变量对象,确定作用域链,以及this的指向,然后再会执行代码也就是赋值。
玉伯的那篇文章打不开了
很好 学习了!!
应该是作用域的问题吧;
函数的作用域在函数创建阶段建立,并一直保持不变,直到函数销毁。
例如:
var x=10;
function foo(){
alert(x);
}
(function foox(){
var x=20;
foo();
})();//10,not 20
hoisting可以翻译成变量声明提升/声明时机提升
我觉得最后一个问题并不是预解析的问题,
而是if语句块内部允不允许包含函数声明语句的问题。