javascript变量声明及作用域

变量声明

动态与静态语言

       编程语言分为动态(类型)语言和静态(类型)语言,动态类型语言是指在运行期间才去做数据类型检查的语言,也就是说,在用动态类型的语言编程时,永远也不用给任何变量指定数据类型,该语言会在第一次赋值给变量时,在内部将数据类型记录下来。Python、Ruby和JavaScript就是典型的动态类型语言。静态类型语言与动态类型语言刚好相反,它的数据类型是在编译其间检查的,也就是说在写程序时要声明所有变量的数据类型,C/C++是静态类型语言的典型代表,其他的静态类型语言还有C#、Java等。

变量声明提升(hoisting机制)

JavaScript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。

以下代码输出v为undefined

var v = "hello";
(function(){
  console.log(v);
  var v = "world";
})();

以上代码相当于:

var v = "hello";
(function(){
  var v;
  console.log(v);
  v = "world";
})();

由于对变量v的声明被提升到相对于该变量作用域的最前面,所以输出值为undefined。

声明提升

当前作用域内的声明都会被提升到作用域的最前面,包括变量和函数的声明。

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

以上代码相当于:

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

以上代码请注意函数表达式并没有被提升,这也是函数表达式和函数声明的区别:如果函数被声明了,提升的是函数名,否则提升的是函数表达式。

示例:

(function(){
  //var f1,function f2(){}; //hoisting,被隐式提升的声明
 
  f1(); //ReferenceError: f1 is not defined
  f2();
 
  var f1 = function(){};
  function f2(){}
})();

名字解析顺序:

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

名字声明的优先级如上所示,也就是说如果一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,无论其在代码中的顺序如何。但名字的初始化却是按其在代码中书写的顺序进行的,不受以上优先级的影响。看代码:

(function(){
    var foo;
    console.log(typeof foo); //function
     
    function foo(){}
 
    foo = "foo";
    console.log(typeof foo); //string
})();

如果形式参数中有多个同名变量,那么最后一个同名参数会覆盖其他同名参数,即使最后一个同名参数并没有定义。

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

命名函数表达式

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

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

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

作用域

https://blog.csdn.net/yueguanghaidao/article/details/9568071

猜你喜欢

转载自blog.csdn.net/jjy8040/article/details/86303943