函数&自执行函数&函数类型
1、自执行函数特点
- 函数表达式与函数声明不同,函数名只在该函数内部有效,并且此绑定是常量绑定。
- 对于一个常量进行赋值,在
strict
模式下会报错,非strict
模式下静默失败。 IIFE
中的函数是函数表达式,而不是函数声明。
2、函数类型
- 函数声明
- 函数表达式
- 函数构造器创建
1. 函数声明(FD
)
- 有一个特定的名称
- 在源码中的位置:要么处于程序级(
Program level
),要么处于其它函数的主体(FunctionBody
)中 - 在进入上下文阶段创建
- 影响变量对象
- 以下面的方式声明
function funName () {}
2. 函数表达式(FE
)
- 在源码中须出现在表达式的位置
- 有可选的名称
- 不会影响变量对象
- 在代码执行阶段创建
// 函数表达式
var foo = function () {} // 匿名函数表达式赋值给变量foo
var foo2 = function _foo2() {} // 外部FE通过变量“foo”来访问——foo(),而在函数内部(如递归调用),有可能使用名称“_foo”。
// 圆括号(分组操作符)内只能是表达式
(function foo() {});
// 在数组初始化器内只能是表达式
[function bar() {}];
// 逗号也只能操作表达式
1, function baz() {};
// !
!function() {}();
(function foo() {})() // 自执行函数 IIFE
(function () {})() // IIFT
var foo = {
bar: function (x) {
return x % 2 != 0 ? 'yes' : 'no';
}(1)
};
foo.bar // 'yes'
3. 函数构造器创建的函数
我们将它与 FD
和 FE
区分开来。其主要特点在于这种函数的[[Scope
]]属性仅包含全局对象
var x = 10;
function foo() {
var x = 20;
var y = 30;
var bar = new Function('alert(x); alert(y);');
bar(); // 10, "y" 未定义
}
3、如何创建一个函数不需要 () 就可以执行
- 创建对象
- 对象里面表达式定义自执行函数
var foo = {
bar: function (x) {
return x % 2 != 0 ? 'yes' : 'no';
}(1)
};
foo.bar // 'yes'
4、为什么有些要加 ()
有些可以不加?
当函数不在表达式的位置的时候,分组操作符圆括号是必须的——也就是手工将函数转化成 FE
。
如果解析器知道它处理的是 FE
,就没必要用圆括号。
5、具名函数表达式
当函数表达式 FE
有一个名称(称为命名函数表达式,缩写为 NFE
)时,将会出现一个重要的特点。
从定义(正如我们从上面示例中看到的那样)中我们知道函数表达式不会影响一个上下文的变量对象(那样意味着既不可能通过名称在函数声明之前调用它,也不可能在声明之后调用它)。
但是,FE
在递归调用中可以通过名称调用自身。
(function foo(bar) {
if (bar) {
return;
}
foo(true); // "foo" 是可用的
})();
“foo
” 储存在什么地方?在 foo
的活动对象中?不是,因为在 foo
中没有定义任何” foo
”。在上下文的父变量对象中创建 foo
?也不是,因为按照定义—— FE
不会影响 VO
(变量对象)——从外部调用 foo
我们可以实实在在的看到。那么在哪里呢?
当解释器在代码执行阶段遇到命名的 FE
时,在 FE
创建之前,它创建了辅助的特定对象,并添加到当前作用域链的最前端。然后它创建了 FE
,此时(正如我们在第四章 作用域链知道的那样)函数获取了[[Scope
]] 属性——创建这个函数上下文的作用域链)。此后,FE
的名称添加到特定对象上作为唯一的属性;这个属性的值是引用到 FE
上。最后一步是从父作用域链中移除那个特定的对象。
6、自执行函数示例
// 例一
+function foo(){
foo=10;//我的问题代码
console.log(foo);//方法自己
}();
console.log(typeof foo);//undefined 观察是否全局污染
// 例二
var b = 10;
(function b() {
// 内部作用域,会先去查找是有已有变量b的声明,有就直接赋值20,确实有了呀。发现了具名函数 function b(){},拿此b做赋值;
// IIFE的函数无法进行赋值(内部机制,类似const定义的常量),所以无效。
// (这里说的“内部机制”,想搞清楚,需要去查阅一些资料,弄明白IIFE在JS引擎的工作方式,堆栈存储IIFE的方式等)
b = 20;
console.log(b); // [Function b]
console.log(window.b); // 10,不是20
})();
// 严格模式 会报错
var b = 10;
(function b() {
'use strict'
b = 20;
console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."
// 普通函数
function a () {
a = 1
console.log(a)
}
a() // 1
a() // a is not a function
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!