JavaScript函数核心机制详解:定义、调用与作用域
本文深入解析JavaScript函数的核心概念,涵盖构造函数、函数声明与表达式三种定义方式。详细阐述形参与实参的传递规则、值传递与引用传递的理解,以及直接调用、对象方法调用、new实例化及call/apply等四种调用模式。同时解析返回值机制、立即执行函数语法,并系统梳理全局、函数及ES6块级作用域的区别与变量查找规则。
函数简介
函数function
- 在JavaScript中,函数本质上也是一种对象类型。
- 函数是将实现特定功能的若干条语句封装在一起的代码块,在需要执行该功能时即可随时调用。
- 函数具备可执行性,而其他数据类型通常不具备直接执行的特性。
- 使用typeof运算符检查一个函数对象时,返回的结果为function。
使用函数的主要优点包括:
- 提高代码的复用率,避免重复编写相同逻辑。
- 便于代码的阅读与交流,使逻辑结构更加清晰。
创建函数
构造函数创建函数
语法如下:
var fun =new Function(代码块);
这种通过构造函数方式构建函数的情况在实际开发中较少见。
函数声明创建函数
语法格式如下:
function 函数名(形参1,形参2......形参N){
语句...
}
函数表达式创建函数
var 函数名 = function 函数名(形参1,形参2......形参N){
语句...
}
函数的参数
形参(形式参数):
- 在函数定义的括号()中指定一个或多个形参。
- 多个形参之间使用逗号,隔开,声明形参相当于在函数内部声明了对应的变量,但此时并不进行赋值操作。
实参(实际参数):
- 在调用函数时,可以在括号()中指定实参。
- 实参的值将会被赋值给函数中相应的形参。
- 调用函数时,JavaScript解析器不会检查实参的类型,因此需要注意是否可能接收到非法参数,若存在此类风险,则需对参数进行类型检查。
function sum(a, b) {
console.log(a + b);
}
sum(1, 2);//调用函数,传入实参

参数的数量:
- 函数的实参个数和形参个数可以不一致。
- A、实参的个数多于形参的个数:函数正常运行,多余的实参将被忽略。
- B、实参的个数少于形参的个数:多余的形参将变为值为undefined的变量。
问题:在JavaScript中调用函数时传递变量参数,是值传递还是引用传递?
- 理解1:都是值(基本类型值或地址值)传递。
- 理解2:可能是指传递,也可能是引用传递(地址值)。
var a = 3;
function fn(a) {
a = a + 1;
}
fn(a);
console.log("a为:", a);// 3

在这里就可以理解为是值(基本类型值)传递。
var obj = { name: "心猿" };//声明一个对象
function fn(obj) {
console.log(obj.name);
}
fn(obj);//“心猿”
//这里可以理解为地址值传递,也可以理解为引用传递(地址值)

函数的调用
直接调用:
函数名()
function fn(obj) {
console.log("我是直接被调用的!");
}
fn()//直接调用

通过对象调用
obj.函数名()
Obj = {
fun(){
console.log("我是通过对象调用的!");
}
}
Obj.fun();//通过对象调用函数

new调用
new fun()
function fun() {
console.log("我是通过new调用的!");
return 1 + 2;//返回一个值
}
var result = new fun();
console.log("result:", result);//fun {}
console.log("result的数据类型:",typeof result);//"object"

注意:
1、使用new调用函数时,得到的结果永远是一个对象,无论函数内部是否有返回值。
2、使用new调用函数时,该函数即被视为用来创建对象的构造函数。
fun.call/apply(obj)调用
这种方式是临时让fun成为obj的方法进行调用。
var obj = { name: "心猿" };//声明一个对象
function fun() {
this.age = 5000;
console.log("通过fun.call(obj)调用函数!");
}
//不能直接通过obj.fun()调用,但是可以通过fun.call(obj)进行调用
fun.call(obj)//相当于obj.fun
//打印通过fun.call(obj)调用函数!
console.log("还可以当做obj的方法调用age的信息 "+"age:",obj.age);//5000

函数的返回值
函数可以有返回值,也可以没有返回值。
- 有返回值的函数:函数体中通过return语句返回一个值,该返回值决定程序下一步的操作。
- 无返回值的函数:函数仅实现某种功能,不需要返回值(函数体中没有return语句)。
- 返回值可以是任意数据类型,既可以是基本数据类型,也可以是对象和函数。
立即执行函数
函数定义完成后立即被调用,这种函数被称为立即执行函数。
立即执行函数通常只会执行一次。
语法:
(function(){
代码块;
})();
例如:
(function (a, b) {
console.log("num:", a + b);
})(1,3);//4

方法
- 对象中的属性可以是一个函数。
- 如果一个函数作为对象的属性保存,那么我们称这个函数是该对象的方法。
- 调用这个函数即为调用对象的方法(method),其本质与普通函数没有区别。
var obj = new Object()
{
obj.name = "心猿";
obj.age = 3000;
obj.sayName = function(){
console.log("name:",obj.name);
}
}
obj.sayName();

另一种写法:
var obj = {
name: "意马",
age: 3000,
sayName: function () {
console.log("name:", obj.name);
}
}
obj.sayName();

枚举对象中的属性:
可以看我这篇的不同方法遍历的区别:比较JavaScript中for、forEach、for…in、for…of的区别
使用for...in语句
语法
for(var index in arr)
{
console.log(index);//代码块
}
for ...in语句中,对象有几个属性,循环体就会执行几次,每次执行时,会将对象中的一个属性的名字赋值给变量。

var person = {
name:"孙悟空",
age:5777,
gender:"男"
};
for(var index in person)
{
console.log(person[index]);
}
作用域
作用域指一个变量的作用范围。
在JavaScript中一共两种作用域:
1.全局作用域(全局变量)
2.函数作用域(局部变量)
3.块级作用域ES6语法
全局作用域
- 在函数外部定义的变量,或在函数内部没有使用var声明的变量。
- 全局作用域在浏览器页面打开时创建,在页面关闭时销毁。
- 在全局作用域中有一个全局对象window。
- 它代表的是一个浏览器的窗口。
- 它代表的是一个浏览器的窗口,它由浏览器创建,我们可以直接使用。
- 如果在node.js环境下使用这个全局对象window会报错,需要在浏览器中才会有显示结果。
- 在全局作用域中:
- 创建的变量都会作为window对象的属性保存。
- 创建的函数都会作为window对象的方法保存。
- 全局作用域中的变量都是全局变量。
- 在页面任意的部分都可以访问到。
变量作为window对象的属性保存。
var a = 10;
console.log("a:",a);
console.log("window.a:",window.a);
因为环境的原因在node.js下会报错。

在浏览器中会正常显示。

函数都会作为window对象的方法。
function fun(){
console.log("我是window.fun函数!")
}
window.fun();

函数作用域
- 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁。
- 每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的。
- 在函数作用域中可以访问到全局作用域的变量。
- 当函数作用域操作一个变量时,会先在自身作用域中寻找,如果有就直接使用,如果全局作用域中依然没有找到,则会报错
ReferennceError。 - 在函数中要访问全局变量可以使用window对象。
块级作用域
ES6(ECMAScript 2016)使用let声明的变量,作用范围在语句块中。
for(let i=0;i<100;i++){
}
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注本站的更多内容!
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
JavaScript函数定义的三种方式:声明、表达式与箭头函数
2026-11-05 13:50:55
JavaScript中escape、encodeURI和encodeURIComponent对空格的处理差异
2026-11-05 12:47:23
