函数
定义函数的方式
火狐、谷歌、safari、opera 存在属性 name 可以访问当前函数的 name
函数声明
函数声明提升,即执行代码前会先读取函数声明
1 2 3 4 5
| func(); function func(...args) { console.log(func.name); }
|
函数表达式
又称匿名函数或拉姆达函数
1 2 3 4 5
| func(); var func = function (...args) { console.log(func.name); };
|
递归调用
arguments.callee
指向正在执行的函数指针
1 2 3
| function func(...args) { console.log(arguments.callee.name); }
|
闭包
有权访问另一个函数作用域中变量的函数
执行环境和作用域
- 执行环境:定义变量或函数有权访问的其它数据
- 变量对象:与执行环境相关联的对象,环境中定义的所有变量或函数都保存在这个对象中
- 函数环境:将活动对象作为变量对象,活动对象最开始只包含一个对象,即 arguments 对象
闭包与变量
闭包中保存的是整个变量对象,闭包中引用的变量都是指向这个环境变量对象的对应属性地址,而不是具体的值,在这个环境变量中定义的任何变量若不手动销毁都会一直存在一个引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| var arr = []; function test() { for (var i = 0; i < 4; i++) { arr[i] = function () { console.log(i); }; } } test(); arr[2]();
var arr = []; function test() { for (var i = 0; i < 4; i++) { arr[i] = (function (j) { return function () { console.log(j); }; })(i); } } test(); arr[2]();
|
this 对象
匿名函数执行环境具有全局性。函数在调用时会自动获取 this 和 arguments 这两个对象,内部函数在搜索这两个变量时,只会搜索到活动对象为止
1 2 3 4 5 6 7 8 9 10 11 12 13
| var name = "window"; var test = { name: "test", getName: function () { return function () { console.log(this.name); }; }, };
test.getName()();
|
模仿块级作用域
通过立即执行函数的方法模仿块级作用域
私有变量
通过闭包的方式在外层创建局部变量的方式实现私有变量,在内部函数中定义的可以操作外部私有属性的方法叫做特权方法
静态私有变量
通过在原型中利用闭包的方式定义一个局部变量,然后在原型上定义一些特权方法实现对该变量的操作,实现所有实例共享同一个变量的方法
1 2 3 4 5 6 7 8 9 10 11 12
| (function () { let test = name; return function Sup(name) { this.prototype.getName = function () { return test; };
this.prototype.setName = function (temp) { test = temp; }; }; })();
|
模块模式
- 单例:只有一个实例的对象
- 模块模式:通过对单例添加私有变量和特权方法增强单例
1 2 3 4 5 6 7 8 9 10 11
| const app = (function () { const arr = []; return { getCount: function () { return arr.length; }, addComp: function (comp) { arr.push(comp); }, }; })();
|
增强的模块模式
通过实例对象,注入更多的属性
1 2 3 4 5 6 7 8
| const app = (function () { const obj = new Object(); let len = 10; obj.getCount = function () { return len; }; return obj; })();
|