js基础之变量声明提高

变量声明的提高

这是js特有的一个特色,其余语言都没有这个特色。有些程序员挺反感这个特色的。javascript

咱们如今先去改变变量的值,而后定义变量,因为JS有一个机制,叫作变量声明的提高,java

javascript的变量声明具备hoisting机制,JavaScript引擎在执行的时候,会把全部变量的声明都提高到当前做用域的最前面。程序员

因此如今程序在执行前会已经看见这个程序中有一行定义变量,因此就会提高到程序开头去运行函数

1
2
3
4
5
6
7
8
9
var v = 'hello';
(function(){
 
  console.log(v);
 
  var v = 'world'
 
})()
 
 
 
 
 
 
 
 
 
 
 
//结果为undefined
 
 
1
2
3
4
5
6
7
8
9
var v = 'hello';
if(true){
 
  console.log(v);
 
  var v = 'world'
 
}

 

 

 

 

 

 

 

 

输出结果为”hello”,说明javascript是没有块级做用域的函数是JavaScript中惟一拥有自身做用域的结构。this

 

由于javascript为动态语言,其变量并无固定的类型,其存储空间大小会随初始化与赋值而变化,因此其变量的“定义”就不像传统的静态语言同样了,其定义显得可有可无。spa

声明提高code

当前做用域内的声明都会提高到做用域的最前面,包括变量和函数的声明ip

1
2
3
4
5
6
( function (){
   var  a = "1" ;
   var  f = function (){};
   var  b = "2" ;
   var  c = "3" ;
})();

 

 

 

 

变量a,f,b,c的声明会被提高到函数做用域的最前面,相似以下:ci

1
2
3
4
5
6
7
( function (){
   var  a,f,b,c;
   a = "1" ;
   f = function (){};
   b = "2" ;
   c = "3" ;
})();

 

 

 

 

请注意函数表达式并无被提高,这也是函数表达式与函数声明的区别。进一步看两者的区别:作用域

1
2
3
4
5
6
7
8
9
( function (){
   //var f1,function f2(){}; //hoisting,被隐式提高的声明
 
   f1(); //ReferenceError: f1 is not defined
   f2();
 
   var  f1 = function (){};
   function  f2(){}
})();

 

 

 

 

 

上面代码中函数声明f2被提高,因此在前面调用f2是没问题的。虽然变量f1也被提高,

但f1提高后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。因此只有声明是被提高的。

不写var

        abc = 123;

        console.log(abc);//123

        定义abc的时候没有写var,程序没有报错,说明这个abc变量真的已经被定义成功了。

        不写var定义了一个全局变量,做用域是不能控制的

javascript中一个名字(name)以四种方式进入做用域(scope),其优先级顺序以下:
一、语言内置:全部的做用域中都有 this 和 arguments 关键字
二、形式参数:函数的参数在函数做用域中都是有效的
三、函数声明:形如function foo() {}
四、变量声明:形如var bar;

名字声明的优先级如上所示,也就是说若是一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,

不管其在代码中的顺序如何。但名字的初始化倒是按其在代码中书写的顺序进行的,不受以上优先级的影响。看代码:

1
2
3
4
5
6
7
8
9
( function (){
     var  foo;
     console.log( typeof  foo); //function
     
     function  foo(){}
 
     foo = "foo" ;
     console.log( typeof  foo); //string
})();

 

 

 

 

 

若是形式参数中有多个同名变量,那么最后一个同名参数会覆盖其余同名参数,即便最后一个同名参数并无定义。

以上的名字解析优先级存在例外,好比能够覆盖语言内置的名字arguments。

命名函数表达式

能够像函数声明同样为函数表达式指定一个名字,但这并不会使函数表达式成为函数声明。命名函数表达式的名字不会进入名字空间,也不会被提高。

1
2
3
4
5
f(); //TypeError: f is not a function
foo(); //ReferenceError: foo is not defined
var  f = function  foo(){console.log( typeof  foo);};
f(); //function
foo(); //ReferenceError: foo is not defined

 

 

 

命名函数表达式的名字只在该函数的做用域内部有效。

相关文章
相关标签/搜索