函数定义
定义函数方法有两种:声明式 和 表达式
1.声明式(普通形),略
2.表达式(赋值形)
匿名函数(anonymous function)、有时候也叫拉姆达函数。存在函数声明提升问题、闭包this指针问题
函数声明提升问题(function declaration hoisting): 声明式放在哪里都没问题。但是如果是表达式的函数,调用时不能放在定义之后的!
sayHi(); //错误:函数还不存在
var sayHi = function(){
alert("Hi!");
}; 递归(带名字的lambda函数实现)
arguments.callee是当前执行函数的指针,但是在严格模式下不允许访问。所以通过带名字的lambda函数实现
var factorial = (function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
}); 闭包 (解决GC回收内存释放、块级作用域等问题)
闭包是指有权访问其他函数作用域中的变量的函数。换言之就是有不是自己变量的函数,就是闭包。
创建闭包的常见方式,就是在一个函数内部创建另一个函数。
详细理解作用域链: 在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域
function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
} else {
return 0;
}
};
}
var compareNames = createComparisonFunction("name"); //创建函数
var result = compareNames({ name: "Nicholas" }, { name: "Greg" }); //调用函数
compareNames = null; //解除对匿名函数的引用(以便释放内存)
var name = "The Window";
var object = {
name : "My Object",
getName: function(){
return this.name;
} ,
getNameFunc : function(){
var that = this; //这一行是关键,通常也有let self = this的默认命名
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()()); //"My Object"模仿块级作用域
其中的变量 now 现在是匿名函数中的局部变量,而我们不必在全局作用域
中创建它。
(function(){
var now = new Date();
if (now.getMonth() == 0 && now.getDate() == 1){
alert("Happy new year!");
}
}
)(); 模拟私有变量(模块模式)
JavaScript 是以对象字面量的方式来创建单例对象的。简言之,如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有数据的方法,那么就可以使用模块模式。
var application = function(){
var components = new Array(); //私有变量和函数
components.push(new BaseComponent()); //初始化
var app = new BaseComponent(); //创建 application 的一个局部副本
//公共接口
app.getComponentCount = function(){
return components.length;
};
app.registerComponent = function(component){
if (typeof component == "object"){
components.push(component);
}
};
return app;
}();
//返回这个副本 在 Web 应用程序中,经常需要使用一个单例来管理应用程序级的信息。这个简单的例子创建了一个用于管理组件的 application 对象。在创建这个对象的过程中,首先声明了一个私有的 components数组,并向数组中添加了一个 BaseComponent 的新实例(在这里不需要关心 BaseComponent 的代码,我们只是用它来展示初始化操作)。而返回对象的 getComponentCount()和 registerComponent()方法,都是有权访问数组 components的特权方法。前者只是返回已注册的组件数目,后者用于注册新组件。


京公网安备 11010502036488号