- 隐藏内部实现
- 最小授权原则 -- 最小限度地暴露必要内容。
- 所以不会将变量和函数都声明在全局作用域中
-
function doSomething(a) { b = a + doSomethingElse(a * 2); console.log(b * 3); } function doSomethingElse(a) { return a - 1; } var b; doSomething(2); // 15
变量b和函数doSomethingElse()是函数doSomething()的私有内容,外部作用域可以访问到是危险的,下面将私有内容隐藏在函数内部。
-
function doSomething(a) { var b; function doSomethingElse(a) { return a - 1; } b = a + doSomethingElse(a * 2); console.log(b * 3); }
-
- 隐藏的作用
- 避免变量覆盖
- 第三方库中将需要暴露的功能加入命名空间
- 模块
- 避免变量覆盖
- 函数作用域
-
var c = 'hey'; function bo() { var c = 'hi'; console.log(c); } bo(); // hi console.log( c ); // hey
上述代码的问题
-
函数bo()‘污染’了所在作用域,因为是一个具名函数
- 只能显式地通过函数名调用函数
-
- 期待能够不要函数的名字,并且没有名字也可以运行
-
var c = 'hey'; (function bo() { var c = 'hi'; console.log(c); // hi })(); console.log(c); // hey
- 区分函数和函数表达式就是看function关键字是否是声明的第一个词。
- 上面代码中,function前还有一个 '(' ,所以是函数表达式
- 所以 (function bo(){ .. }) 只能在 .. 中访问,不能被外部作用域访问。变量名bo被隐藏在自身中,最小授权
-
- 匿名和具名
- 匿名函数表达式的缺点
- 调试时,栈内并没有函数名
- 函数表达式递归时,只能用arguments.callee
- 可读性降低
- 行内函数表达式 -- 具名
-
setTimeout( function() { console.log('等1秒!'); }, 1000 ); // 行内函数表达式 setTimeout( function timeoutHandler() { console.log('等1秒!'); }, 1000 );
- 匿名函数表达式的缺点
- Immediately Invoked Function Expression --- 立即执行函数表达式
-
var word = 'hi'; (function IIFE() { var word = 'hey'; console.log(word); // hey })(); console.log( word ); // hi
函数IIFE中第一个括号将函数定义为函数表达式,第二个括号使函数立即运行
下面是IIFE的另一种形式,将第二个括号写入第一个括号里 -
var word = 'hi'; ( function IIFE() { var word = 'hey'; console.log(word); // hey }() ); console.log( word ); // hi
- 作用
- 匿名函数表达式
- 作为主调函数,传递参数
-
var say = 'hi'; (function IIFE(global){ var say = 'hey'; console.log(say); // hey console.log(global.say); // hi }(window)); console.log(say); // hi
- 避免undefined的默认值被错误覆盖导致的异常(我还没见过)
undefined = true; (function IIFE( undefined ) { var a; if (a === undefined) { console.log('Undefined is safe here!'); } })();
- 倒置代码的运行顺序
say = 'hi'; (function run1(func) { func(window); })( function run2(global) { var say = 'hey'; console.log(say); // hey console.log(global.say); // hi });
函数run2在函数run1执行之后当作参数传进去
-
-
-
- 块作用域
- 为什么引入块作用域?
var a = true; if (a) { var b = a * 2; console.log( b ); }
尽管变量b声明在块作用域内,但是var声明的变量不具有块作用域的特性,所以变量b被绑定在全局作用域内,污染了全局作用域,破坏了最小暴露原则。
- 块作用域可以将隐藏在函数内的信息扩展为块中隐藏的信息。所以能提高代码的可维护性。
- with的块作用域(不懂)
- try...catch中catch的作用域,没遇到过,先放着
- 为什么引入块作用域?