浅谈js中函数作用域和声明提前

JavaScript的函数具有两个主要特性,一是函数是一个对象,二是函数提供作用域支持,今天主要聊聊函数的作用域支持。

简单看两个概念:

  具名函数表达式

  

var add = function add (a) {
         return a    
    }

这段代码描述了一个函数,称为‘具名函数表达式’。

如果省略函数表达式中的名字,它就是‘匿名函数表达式’,即匿名函数,例如

var add = function (a, b) {
    return a + b;
};

最后看下‘函数声明’

function foo() {
    // 函数体
}

函数声明只能出现在“程序代码”中,也就是说在别的函数体内或在全局。这个定义不能赋值给变量或属性,同样不能作为函数调用的参数。

//全局作用域

function foo() {}

//本地作用域

function local() {
    function bar() {}
    return bar;
}

此时的bar就是在local内,也就是在外面时访问不到的,被称之为局部作用域,那既然这样,我们看下面这段代码

var a = 1;
function aa(){
     console.log(a);  
}

此时输出的结果是1,很好理解,因为在函数内部访问不到,因此会去外面寻找,直到找到为止

添加一行代码,再看看

var a = 1;
function(){
   console.log(a);
   var a =2 ;  
}

此时输出结果是underfined;很诧异,没有定义之前可以在函数外部访问到,定义了反而访问不了了,实际情况是什么呢,js在函数内部定义的变量会提升至函数体顶部,但仅仅是定义,并未赋值,因此上述代码是这样的

var a = 1;
function(){
   var a;  
   console.log(a);
   var a =2 ;  
}

既然a定义了,但没赋值,所以console之后当然underfined啦。

既然函数声明会提升,那函数表达式会不会呢,看下面这个例子

// 全局函数
function foo() {
    alert('global foo');
}
function bar() {
    alert('global bar');
}

function hoistMe() {

    console.log(typeof foo); 
    console.log(typeof bar); 

    foo(); 
    bar(); 

    function foo() {
        alert('local foo');
    }

    var bar = function () {
        alert('local bar');
    };
}
hoistMe();

经过上次的代码,这次就比较容易理解了,里面的函数会覆盖外面定义的函数,但是结果都是什么呢

    console.log(typeof foo); // "function"
    console.log(typeof bar); // "undefined"

    foo(); // "local foo"
    bar(); // TypeError: bar is not a function

是不是有点诧异呢,仔细想想也很容易明白

刚才说了,函数声明会提前,所以 变量foo和它的定义实现都被提前了,而且函数定义实现和书写顺序无关的,这里故意写在后面也证明了这一点。

但是函数表达式却没有这个技能,所以变量被提前,而定义却没有提前.

谢谢观看

posted @ 2015-04-03 13:37  catboy1006  阅读(108)  评论(0编辑  收藏  举报