Javascript 两种 function 定义的本质区别

本文探讨JavaScript中两种常见函数定义方式的区别,分析函数声明与赋值给变量时的行为差异,并解释变量与函数声明的提升机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

两种常见的function定义:

1⃣️

var func = function(){
...
}

2⃣️

function func(){
...
}
两种定义方式在表现形式上的不同:

第一种var方式定义的函数,不能先调用,后声明;只能先声明,后调用。
第二种function方式定义函数可以先调用,后声明。

(function($) {

    var a = 1;
    var b = 2;


    func1();
    var func1 = function () {
        alert("func1");
    }


    func2();
    function func2() {
        alert("func2");
    }

    $(document).ready(function () {
        alert("ready");
    });

}($));

运行结果:
这里写图片描述


(function($) {

    var a = 1;
    var b = 2;


    var func1 = function () {
        alert("func1");
    }
    func1();


    func2();
    function func2() {
        alert("func2");
    }

    $(document).ready(function () {
        alert("ready");
    });

}($));
运行结果:

这里写图片描述


两种定义方式效果不同的本质原因:声明“被提前”
变量声明“被提前”
(function() {
  // Output: undefined
  console.log(declaredLater);

  var declaredLater = "Now it's defined!";

  // Output: "Now it's defined!"
  console.log(declaredLater);
})();

这其实是 JavaScript 解析器搞的鬼,解析器将当前作用域内声明的所有变量和函数都会放到作用域的开始处,但是,只有变量的声明被提前到作用域的开始处了,而赋值操作被保留在原处。上述代码对于解析器来说其实是如下这个样子滴:

(function() {
  var declaredLater; //声明被提前到作用域开始处了!

  // Output: undefined
  console.log(declaredLater);

  declaredLater = "Now it's defined!"; //赋值操作还在原地!

  // Output: "Now it's defined!"
  console.log(declaredLater);
})();

变量和函数经过“被提前”之后,declaredLater 变量其实就被放在了调用函数的前面。根据 JavaScript 语法的定义,已声明而未被赋值的变量会被自动赋值为 undefined 。所以,第一次打印 declaredLater 变量的值就是 undefined,后面我们对 declaredLater 变量进行了赋值操作,所以,第二次再打印变量就会输出Now it’s defined!

再来看一个更有意思的栗子:

var name = "haha";

(function () {
    // Output: "Original name was undefined"
    console.log("Original name was " + name);

    var name = "test";

    // Outputs: "New name is test"
    console.log("New name is " + name);
})();

我们本来希望在第一次打印 name 变量时能够输出全局范围内定义的 name 变量,然后再在函数中定义一个局部 name 变量覆盖全局变量,最后输出局部变量的值。可是第一次输出的结果和我们的预期完全不一致,原因就是我们定义的局部变量在其作用域内被“提前”了,也就是变成了如下形式:

var name = "haha";

(function () {
    var name;  //注意:name 变量被提前了!

    // Outputs: "Original name was undefined"
    console.log("Original name was " + name);

    name = "test";

    // Outputs: "New name is test"
    console.log("New name is " + name);
})();

函数声明“被提前”

上面讲述的是变量声明,接下来我们回归正题,说说函数。
函数的“被提前”还要分两种情况:
第一种:函数声明;
第二种:函数作为值赋值给变量;

函数声明:

 func2();//输出“func2”

 function func2() {
        alert("func2");
    }

如上所示,JavaScript 解释器允许你在函数声明之前使用,也就是说,函数声明并不仅仅是函数名“被提前”了,整个函数的定义也“被提前”了!所以上述代码能够正确执行。

函数作为值赋值给变量:

func1();//浏览器报错,提示“func1 is not a function”

var func1 = function () {
        alert("func1");
    }

func1变量“被提前”了,但是他的赋值(也就是函数主体实现)并没有被提前,从这一点上来说,和前面我们所讲的变量“被提前”是完全一致的;并且,由于“被提前”的变量的默认值是 undefined ,所以报的错误属于“类型不匹配”,因为 undefined 不是函数,当然不能被调用,如下图:

(function($) {

    var a = 1;
    var b = 2;

    alert(func1);

    var func1 = function () {
        alert("func1");
    }
    func1();


    func2();
    function func2() {
        alert("func2");
    }

    $(document).ready(function () {
        alert("ready");
    });

}($));

这里写图片描述

总结:
1⃣️变量的声明被提前到作用域顶部,赋值保留在原地;
2⃣️函数声明整个“被提前”;
3⃣️函数作为值赋给变量时只有变量“被提前”了,函数没有“被提前”;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值