这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
因为我在写这文章的时候,百度里找资料,找到了园友的一篇文章,写的很好,可是我写了又不想放弃,所以就在里面拿了很多东西过来!~~
因为这个问题很是经典,而且容易出错,所以在介绍一次。哈哈。莫怪哦。
[翻译]JavaScript Scoping and Hoisting希望得到大家谅解。
一。案发现场我们先看一段很简单的代码:
- var v='Hello World';
- alert(v);
这个没有疑问吧,弹出 "Hello World"。OK,我们继续。 我们在看一段 Code:
- var v='Hello World';
- (function(){
- alert(v);
- })()
经过运行之后,我们发现,还是和我们预期的一样,弹出了 "Hello World"。 好了,有意思的来了。接着在看一段下面的代码:
- var v='Hello World';
- (function(){
- alert(v);
- var v='I love you';
- })()
如果这个是一个面试题,面试官问你这个结果是多少?你怎么回答? 我们先看结果吧!
结果是 undefined?和你上面自己想的一样吗? 好吧,我就不故弄玄虚了。其实,这里面隐藏了一个陷阱 -----JavaScript 中的变量提升(Hoisting);
二。深度剖析现在我来解释下提升是什么意思?顾名思义,就是把下面的东西提到上面。在 JS 中,就是把定义在后面的东东(变量或函数)提升到前面中定义。 在解释提升之前,我们先来看一下 js 中的作用域(scoping)问题。 对于 JavaScript 新手来说 scoping 是最令人困惑的部分之一。事实上,不仅仅是新手,我遇到或很多有经验的 JavaScript 程序员也不能完全理解 scoping。JavaScript 的 scoping 如此复杂的原因是它看上去非常像 C 系语言的成员。请看下面的 C 程序:
- #include <stdio.h>
- int main() {
- int x = 1;
- printf("%d, ", x); // 1
- if (1) {
- int x = 2;
- printf("%d, ", x); // 2
- }
- printf("%d\n", x); // 1
- }
这段程序的输出是 1,2,1。这是因为在 C 系语言有块级作用域 (block-level scope), 当进入到一个块时,就像 if 语句,在这个块级作用域中会声明新的变量,这些变量不会影响到外部作用域。但是 JavaScript 却不是这样。在 Firebug 中试试下面的代码:
- var x = 1;
- console.log(x); // 1
- if (true) {
- var x = 2;
- console.log(x); //2
- }
- console.log(x);// 2
在这段代码中,Firebug 显示 1,2,2。这是因为 JavaScript 是函数级作用域 (function-level scope)。这和 C 系语言是完全不同的。块,就像 if 语句,并不会创建一个新的作用域。只有函数才会创建新的作用域。 对于大部分熟悉 C,C++,C# 或是 Java 的程序员来说,这是意料之外并且不被待见的。幸运的是,因为 JavaScript 函数的灵活性,对于这个问题我们有一个解决方案。如果你必须在函数中创建一个临时的作用域,请像下面这样做:
- function foo() {
- var x = 1;
- if (x) {
- (function () {
- var x = 2;
- // some other code
- }());
- }
- // x is still 1.
- }
这种方面确实非常灵活,它使用在任何需要创建一个临时作用域的地方,不仅仅是某个块中。但是,我强烈建议你花点时间好好理解下 JavaScript scoping。它实在是非常强力,而且它也是我最喜欢的语言特性之一。如果你很好的理解了 scoping,理解 hoisting 将会更加容易。 2.1 变量提升 变量提升,很简单,就是把变量提升提到函数的 top 的地方。我么需要说明的是,变量提升 只是提升变量的声明,并不会把赋值也提升上来。 比如: 我们定义三个变量:
- (function(){
- var a='One';
- var b='Two';
- var c='Three';
- })()
实际上它是这样子的:
- (function(){
- var a,b,c;
- a='One';
- b='Two';
- c='Three';
- })()
这个时候就把变量提升了呀。 好,我们现在回到第一段 code 里面。为什么会报错呢?其实,根据我么根据上面变量提升原件以及 js 的作用域(块级作用域)的分析,得知 上面代码真正变成如下:
- var v='Hello World';
- (function(){
- var v;
- alert(v);
- v='I love you';
- })()
左边报错了。没骗你。 应该到这里基本都可以弄懂了。~ 呵呵。。 再次谢谢 Beta Rabbit 作者:Lanny☆兰东才
所以,才会提示说 "undefined"。 从这里,我们也学习到,我们在写 js code 的时候,我么需要把变量放在块级作用域的顶端,比如我在上面所举的例子:var a,b,c;。防止出现意外。 2.2 函数提升 函数提升是把整个函数都提到前面去。 在我们写 js code 的时候,我们有 2 中写法,一种是函数表达式,另外一种是函数声明方式。我们需要重点注意的是,只有函数声明形式才能被提升。 函数声明方式提升【成功】 函数表达式方式提升【失败】 结果如下:
来源: http://www.phperz.com/article/17/0424/281794.html