本文地址:http://blog.163.com/jinlu_hz/blog/static/113830152201131132035178/
原文地址:http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
原文做者:ben cherry
在前篇小议javascript之全局对象建立译文中提到过JavaScript Hoisting概念,当时不甚了解。google以后发现ben cherry解释的最为明了,因而有了本文这篇干货翻译稿。
翻译能力有限,辞不达意的地方请自动跳过或者直接阅读原文。
——如下为翻译——
JavaScript Scoping and Hoisting(JavaScript中的做用域与变量声明提高/声明时机提高)
你知道下面JavaScript代码的执行结果是什么吗?
javascript
foo = ; bar() (!foo) foo = ; alert(foo); bar();若是你对foo的值实际上为"10"而感到诧异的话,再看一下下面这个例子:
a = ; b() a = ; ; a() b(); alert(a);
<stdio.h> main() { x = ; printf(, x); () { x = ; printf(, x); } printf(, x); }
if
语句中时,当前做用域中的新变量会被声明,而且不会影响到外部做用域。但在JavaScript中状况并非这样:
x = ; console.log(x); (true) x = ; console.log(x); console.log(x);
if
语句中的代码块并不会建立新的做用域,只有函数才会。
foo() x = ; (x) ( () x = ; ());这个函数很是灵活,不只仅在块级语句内,须要时能在任何地方使用。然而我强烈建议你多花点时间来理解JavaScript的做用域。
语言级别:默认在所用做用域下会定义this
、arguments
html
传入参数:函数命名的参数,做用域是当前函数体java
函数声明:例如function foo() {}程序员
变量声明:例如var foo;浏览器
//以上翻译地比较晦涩,建议直接看原文
函数声明与变量声明常常被JavaScript引擎隐式地提高到当前做用域的顶部,也就是说:
ide
foo() bar(); x = ;实际上会被解释成:
foo() x; bar(); x = ;也就是说,下面两种声明方式是等价的:
foo() (false) x = ; ; y = ; foo() x, y; (false) x = ; ; y = ;
test() foo(); bar(); foo = () alert(); bar() alert(); test();这个例子中,只有包含函数体的函数声明会被提高声明。foo虽然会被提高声明,可是函数体却在执行中被赋值。以上就是提高声明时机的基本概念,看起来一点也不复杂。
原生变量arguments
特立独行,包含了传递到函数中的参数。若是自定义以arguments
为命名的参数,将会阻止原生arguments
对象的建立。因此勿使用arguments
为名称的参数。函数
胡乱使用this
标识符会引发语法错误。this
若是多个参数具备相同的命名,那么最后一个参数会优先于先前的,即时这个参数未定义。google
Named Function Expressions(函数命名表达式)
你能够经过函数表达式给函数命名,语法上看起来像是函数声明,实则不是。上一段代码:
编码
foo(); bar(); baz(); spam(); foo = () ; bar() ; baz = spam() ; foo(); bar(); baz(); spam();
foo(a, b, c) x = , bar, baz = ;