函数表达式
函数声明提升
会在代码执行前先读取函数声明,但是不会读取函数表达式。
同环境下不要尝试重载一个函数声明,即使是控制语句中。
递归
递归中要注意函数的变化 :
function factorial(num) {
if (num <= 1) {
return 1
} else {
// 使用 arguments.callee 而不是 factorial
// 能防止在外界将 factorial 设为 null 而引发的错误
return num * arguments.callee(num - 1)
}
}
当然也可以使用命名函数表达式来避免错误:
var factorial = (function f(num) {
if (num <= 1) {
return 1
} else {
return num * f(num - 1)
}
})
闭包
闭包的作用域链会携带包含他的函数的作用域,所以要注意闭包的使用量,避免占用过多内存。
需要注意的是,闭包里携带的是指向变量的指针,而非单纯的变量值:
function createFunction() {
var result = new Array
for (var i = 0; i < 10; i += 1) {
result[i] = function() {
return i
}
}
return result
}
alert(createFunction()[4]()) // 10 ,因为函数结束后 i = 10
当然也有解决方案:
function createFunction() {
var result = new Array
for (var i = 0; i < 10; i += 1) {
result[i] = function(num) {
return function() {
return num
}
}(i)
}
return result
}
模仿块级作用域
可以用这种方式实现块级作用域:
// 这样形式的块级表达式的上面一条语句需要分号
(function() {
// 这里是块级作用域
})()
或者这样来摆脱括号:
_ = function() {
// 这里是块级作用域
}()
私有变量
通过声明变量,而非使用 this
:
function MyObject() {
// 使用 var 而非 this.
var privateValue = 0
// 访问方法
this.getPrivateValue = function() {
return privateValue
}
}
静态私有变量
将静态私有变量放在块级作用域里实现访问阻塞:
_ = function() {
var name = ""
Person = function(value) {
name = value
}
Person.prototype.getName = function() {
return name
}
Person.prototype.setName = function(value) {
name = value
}
}()
模块模式
可以这样实现一个单例:
var application = function() {
var components = new Array()
components.push(new BaseComponent())
return {
getComponentCount: function() {
return components.length
},
registerComponent: function(component) {
if (typeof component == "object") {
components.push(component)
}
}
}
}