执行上下文-作用域链-闭包
1.1 执行上下文-作用域链-闭包
理解 JavaScript 中的执行上下文和执行栈
JavaScript 中有三种执行上下文类型。全局、函数、Eval执行上下文。
在全局执行上下文中,this 的值指向全局对象。(在浏览器中,this引用 Window 对象)。
` 在函数执行上下文中,this 的值取决于该函数是如何被调用的。如果它被一个引用对象调用,那么 this 会被设置成那个对象,否则 this 的值被设置为全局对象或者 undefined(在严格模式下)
1. 立即执行函数
;(function () {
// 代码
})()
1
2
3
2
3
2. 闭包
对于闭包(closure),当外部函数返回之后,内部函数依然可以访问外部函数的变量。
闭包的方法是通过背包的类比, 当一个函数被创建并传递或从另一个函数返回时,它会携带一个背包。
背包中是函数声明时作用域内的所有变量。
3. 使用闭包定义私有变量
通常,JavaScript开发者使用下划线作为私有变量的前缀。但是实际上,这些变量依然可以被访问和修改,并非真正的私有变量。这时,使用闭包可以定义真正的私有变量:
4. prototype
每个JavaScript构造函数都有一个prototype属性,用于设置所有实例对象需要共享的属性和方法。
prototype属性不能列举。JavaScript仅支持通过prototype属性进行继承属性和方法。
5. 模块化
JavaScript并非模块化编程语言,至少ES6落地之前都不是。然而对于一个复杂的Web应用,模块化编程是一个最基本的要求。
这时,可以使用立即执行函数来实现模块化,正如很多JS库比如jQuery以及我们Fundebug都是这样实现的。
所谓模块化,就是根据需要控制模块内属性与方法的可访问性,即私有或者公开。
6. 变量提升
JavaScript会将所有变量和函数声明移动到它的作用域的最前面,这就是所谓的变量提升(Hoisting)。也就是说,无论你在什么地方声明变量和函数,解释器都会将它们移动到作用域的最前面。因此我们可以先使用变量和函数,而后声明它们。
7. 柯里化
柯里化,即Currying,可以是函数变得更加灵活。
我们可以一次性传入多个参数调用它;也可以只传入一部分参数来调用它,让它返回一个函数去处理剩下的参数。
8. apply, call 与 bind 方法
JavaScript开发者有必要理解apply、call与bind方法的不同点。它们的共同点是第一个参数都是this,即函数运行时依赖的上下文。
三者之中,call方法是最简单的,它等价于指定this值调用函数:
apply方法与call方法类似。两者唯一的不同点在于,apply方法使用数组指定参数,而call方法每个参数单独需要指定
使用bind方法,可以为函数绑定this值,然后作为一个新的函数返回:
9. Memoization
Memoization用于优化比较耗时的计算,通过将计算结果缓存到内存中,这样对于同样的输入值,下次只需要中内存中读取结果。
例如,将每个执行结果都存入函数内部作用域中的值中。
10. 函数重载
所谓函数重载(method overloading),就是函数名称一样,但是输入输出不一样。或者说,允许某个函数有各种不同输入,根据不同的输入,返回不同的结果。
凭直觉,函数重载可以通过if…else或者switch实现,这就不去管它了。
jQuery之父John Resig提出了一个非常巧(bian)妙(tai)的方法,利用了闭包。
、、、、 、、、、 、、、、 、、、、 、、、、 、、、、 、、、、 、、、、
