【示例】讲解JavaScript IIFE 与函数调用
作者:admin 时间:2022-6-9 1:2:28 浏览:在JavaScript的函数调用时,常常见到 IIFE 这个词,它其实是“立即调用函数表达式”的英文缩写,在本文中,我将介绍什么是 IIFE,它与调用函数又有什么关系。
我们先看一个简单的函数调用示例,随后再介绍 IIFE 与函数调用的关系。
function hello(name) {
return 'Hello ' + name + '!';
}
// 函数调用
const message = hello('World');
hello('World')
就是一个函数调用。
何为函数调用?
我们可以这样定义:
当计算结果为函数对象的表达式,后跟一对括号
()
,括号内用逗号,
分隔的参数表达式列表时,这就是函数调用。例如 parseInt('18')。
上面示例中,hello
表达式计算为一个函数对象,后跟一对带World
参数的括号()
。
函数调用表达式不能是属性访问器 obj.myFunc()
,这是方法调用,例如[1,5].join(',')
不是函数调用,而是方法调用。请记住它们之间的区别。
函数调用示例
function myFunction(a, b) {
return a * b;
}
myFunction(10, 2); // 20
上面的函数不属于任何对象。
在浏览器中,页面对象是浏览器窗口。上面的函数自动变成了窗口函数。因此,myFunction()
和 window.myFunction()
是同一个函数:
function myFunction(a, b) {
return a * b;
}
window.myFunction(10, 2); // 20
何为 IIFE?
IIFE全称是立即调用函数表达式(英文:immediately-invoked function expression,缩写:IIFE),IIFE 也是一个函数调用。让我们看一个 IIFE 的简单例子:
// IIFE
const message = (function(name) {
return 'Hello ' + name + '!';
})('World');
第一对括号(function(name) {...})
是计算结果为函数对象的表达式,然后是一对带'World
'参数的括号:('World')
。
IIFE 用法
立即调用函数表达式拥有数种不同的写法。最常见的一种是将函数表达式字面量至于圆括号(分组运算符)之内,然后使用圆括号调用函数。
(function() {
// 这里的语句将获得新的作用域
})();
若要将作用域外变量传递进函数,则按下述方式书写:
(function(a, b) {
// a == 'hello'
// b == 'world'
})('hello', 'world');
开头的括号可能会因为解释器的分号自动插入特性造成一些问题。括号本用于明确字面量为表达式以与函数声明语句区分,但解释器可能将括号解释为对以上一行中结尾的变量名为名的函数的调用。在一些省略分号的程序中,可见将分号至于行首的做法。这样的分号被称为“防御性分号”,举例:
a = b + c
;(function() { // 故意将分号放在这里
// 代码
})();
如此书写,以防止语句被理解为对函数c的调用(c(...)
)。
IIFE 例子
理解立即调用函数表达式的关键在于认清JavaScript拥有函数作用域,但没有块作用域(ES6之前),且通过指针(而非复制)将变量传入一个函数闭包。 ES6 引入了新关键字 let
和 const
,用它们定义的常量和变量具有块级作用域。
求值上下文(Evaluation context)
缺少块作用域意味着一个在类似于for循环的块中声明的变量会被置顶到其所包含的函数中。如果一个内部函数依赖于一个外部变量,而该外部变量被外部函数更改,那么执行内函数就有些困难。举例,我们在声明函数之后,但在定义函数之前,改变一个变量的值。
var v, getValue;
v = 1;
getValue = function() { return v; };
v = 2;
getValue(); // 2
当我们手动给v
赋值时这结果似乎没什么问题。不过,如果getValue()
是在一个循环中被定义的,那么就可能出现预想外的结果。
var v, getValue;
v = 1;
getValue = (function(x) {
return function() { return x; };
})(v);
v = 2;
getValue(); // 1
此例中,函数将 v
作为参数传入并立即调用,保护了内部函数的执行上下文。
利用IIFE创建真正的私有函数和变量,并用闭包访问
立即调用函数表达式也可以用来创建私有方法来访问函数,不仅起到保护作用,同时也暴露了一些可以后续使用的属性。
// 'counter' 函数返回一个具有属性的对象, 这里的属性就是
// get set等函数
var counter = (function(){
var i = 0;
return {
get: function(){
return i;
},
set: function( val ){
i = val;
},
increment: function() {
return ++i;
}
};
})();
// 这些调用使用了刚才counter得到的属性
counter.get(); // 0
counter.set( 3 );
counter.increment(); // 4
counter.increment(); // 5
如果我们试图从全局作用域直接访问 counter.i
,会得到 undefined
,因为 i 这个数据由 IIFE 封装,它并不是 counter
的属性。同样的,如果我们试图访问 i
也会收到错误,因为 i
并没有在全局作用域中定义。
总结
本文介绍了JavaScript中的 IIFE 与函数调用,通过本文的学习,我们应该了解了函数调用的定义,知道 IIFE 也是函数调用的一种。
相关文章
- 站长推荐