javascript 作用域的一些小知识
首先,奉献两个题目
1.
1 var foo = 1; 2 function bar() { 3 if (!foo) { 4 var foo = 10; 5 } 6 console.log(foo); //返回10 7 } 8 bar(); 9 /****** 我是分割线******/ 10 var foo = 1; 11 function bar() { 12 if (!foo) { 13 foo = 10; 14 } 15 console.log(foo); //返回1 16 } 17 bar(); 18 19 //why ?
Ctr +A 可以看答案哦~
why?先来看看一下ECMA上的描述
/* * If the variable statement occurs inside a FunctionDeclaration, * the variables are defined with function-local scope in that function. * Otherwise, they are defined with global scope (that is, they are created as members of the global object. * 如果变量声明实在函数内部,那么变量定义的是函数的局部范围,否则它将作为一个全局变量 * * Variables are created when the execution scope is entered. * A Block does not define a new execution scope. Only Program and FunctionDeclaration produce a new scope. * Variables are initialised to undefined when created. * A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement
is executed, * not when the variable is created. * * 变量的创建发生在程序执行到那一步 * 一个语句块并不定义一个新的执行作用域,只有程序和函数声明产生作用域 * 变量初始化的时候被初始化为undefined * 当执行变量声明的时候 ,变量才会由表达式赋值,而并非在变量产生的时候就有 * */
看明白了没?
总结:1.javascript 语言没有JAVA C++ 等块级作用域,if 判断,switch等不会使里面的声明的变量困在其中,而是作为块区域外的变量存在,只有函数声明产生新的作用域。
2.变量的定义|初始化发生在进入程序但是还没执行前,变量初始化为undefined,当程序往下执行时,变量会被表达式赋值,这个时候变量采有值。
看代码,由此我们将上面的代码改成如下!
1 var foo = 1; 2 function bar() { 3 var foo; //undefined,先声明 4 console.log(foo) 5 if (!foo) { 6 foo = 10; //10 7 } 8 console.log(foo); //返回10 9 } 10 bar(); 11 //第二个 12 13 var foo = 1; 14 function bar() { 15 console.log('foo',foo); //1 因为函数体内没有foo,这个时候通过作用域链获取window的foo 变量 16 if (!foo) { 17 foo = 10; 18 } 19 console.log(foo); //返回1 20 } 21 bar();
如何创建一个不影响其它程序的作用域呢,放在闭包内
1 var foo = 1; 2 function bar() { 3 console.log("a",foo) 4 if (foo) { 5 (function(){ 6 var foo = 10; //10 7 console.log('foo',foo) 8 })() 9 } 10 console.log(foo); //返回1 11 } 12 bar();
在javascript中,一个名称进入作用域有四种基本方法( 作用域的提升)
* Language-defined: All scopes are, by default, given the names this and arguments.
* 语言本身所定义的
* Formal parameters: Functions can have named formal parameters,
* which are scoped to the body of that function.
* 函数参数
* Function declarations: These are of the form function foo() {}.
* 函数声明
* Variable declarations: These take the form var foo;.
* 变量声明
function test() { foo(); // TypeError "foo is not a function" bar(); // "this will run!" var foo = function () { // function expression assigned to local variable 'foo' alert("this won't run!"); } function bar() { // function declaration, given the name 'bar' alert("this will run!"); } } test();
如上代码,foo 是没有被定义的,在表达式var foo = function(){} 之前,foo被“提升”到了前面,但是它的主体部份(赋值表达式)要等到执行到它才赋值,因此相当于被赋值为undefined,当执行到这个表达式时 ,它才被赋值为function,因此foo()执行错误。而function bar 是声明,它整体都被“提升”到了最前面,因此可以执行。
总结就是在函数首部定义所有需要的变量,这样就不会产生作用域混淆的问题,最好每个变量前都加var吧!