重温Javascript(四)-函数
函数
函数声明提升,在执行代码之前会先读取函数声明
sayHi(); function sayHi(){
alert("Hi!");
}
递归
arguments.callee是指向正在执行的函数的指针
还可以换种方式达成一样的效果
var factorial = (function f(num){
if (num <= ){
return ;
} else {
return num * f(num-);
}
});
函数执行的作用域链
function compare(value1, value2){
if (value1 < value2){
return -;
} else if (value1 > value2){
return ;
} else {
return ;
}
} var result = compare(, );
先定义了compare()函数,又在全局作用域调用它。当调用时,会创建一个包含arguments、value1、value2的活动对象。全局执行环境的变量对象(包含result和compare)在compare()执行环境的作用域中处于第二位
作用域链本质上是一个指向变量对象的指针列表,只引用但不实际包含变量对象
闭包
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,在一个函数内部创建另一个函数
function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2){
return -;
} else if (value1 > value2){
return ;
} else {
return ;
}
};
}
var compare = createComparisonFunction("name");
var result = compare({ name: "Nicholas" }, { name: "Greg" });
在匿名函数从 createComparisonFunction()中被返回后,它的作用域链被初始化为包含createComparisonFunction()函数的活动对象和全局变量对象。这样,匿名函数就可以访问在createComparisonFunction()中定义的所有变量。createComparisonFunction()
函数在执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象。换句话说,当createComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但它的活动对象仍然会留在内存中;直到匿名函数被销毁后,createComparisonFunction()的活动对象才会被销毁
//创建函数
var compareNames = createComparisonFunction("name"); //调用函数
var result = compareNames({ name: "Nicholas" }, { name: "Greg" }); //解除对匿名函数的引用(以便释放内存)
compareNames = null;
创建的比较函数被保存在变量compareNames 中。而通过将compareNames 设置为等于null解除该函数的引用,就等于通知垃圾回收例程将其清除。随着匿名函数的作用域链被销毁,其他作用域(除了全局作用域)也都可以安全地销毁了。
闭包与变量
function createFunctions(){
var result = new Array(); for (var i=; i < ; i++){
result[i] = function(){
return i;
};
} return result;
}
每个函数都返回10。因为每个函数的作用域链中都保存着createFunctions() 函数的活动对象, 所以它们引用的都是同一个变量i 。
function createFunctions(){
var result = new Array(); for (var i=; i < ; i++){
result[i] = function(num){
return function(){
return num;
};
}(i);
} return result;
}
闭包与this,arguments
每个函数在被调用时都会自动取得2个特殊变量:this和arguments。内部函数在搜索这2个变量时,只会搜索到其活动对象为止,不能直接访问外部函数中的这2个变量。把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以访问了。arguments也是如此。
var name = "The Window"; var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
}; alert(object.getNameFunc()()); //"My Object"
模仿块级作用域
function outputNumbers(count){
for (var i=; i < count; i++){
alert(i);
}
alert(i); //计数
}
通常称为私有作用域
(function(){
//这里是块级作用域
})();
function outputNumbers(count){
(function () {
for (var i=0; i < count; i++){
alert(i);
}
})(); alert(i); //导致一个错误!
}
私有变量
function MyObject(){
//私有变量和私有函数
var privateVariable = 10; function privateFunction(){
return false;
} //特权方法
this.publicMethod = function (){
privateVariable++;
return privateFunction();
};
}
function Person(name){ this.getName = function(){
return name;
}; this.setName = function (value) {
name = value;
};
} var person = new Person("Nicholas");
alert(person.getName()); //"Nicholas"
person.setName("Greg");
alert(person.getName()); //"Greg"
静态私有变量
(function(){ //私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
} //构造函数
MyObject = function(){
}; //公有/特权方法
MyObject.prototype.publicMethod = function(){
privateVariable++;
return privateFunction();
}; })();
未经声明的变量,会创建一个全局变量
但使用prototype的问题时实例变量需要自己定义
(function(){ var name = ""; Person = function(value){
name = value;
}; Person.prototype.getName = function(){
return name;
}; Person.prototype.setName = function (value){
name = value;
};
})(); var person1 = new Person("Nicholas");
alert(person1.getName()); //"Nicholas"
person1.setName("Greg");
alert(person1.getName()); //"Greg" var person2 = new Person("Michael");
alert(person1.getName()); //"Michael"
alert(person2.getName()); //"Michael"
模块模式
单例对象
var singleton = {
name : value,
method : function () {
//这里是方法的代码
}
};
模块模式通过为单例添加私有变量和特权方法使其得到增强
var singleton = function(){ //私有变量和私有函数
var privateVariable = 10; function privateFunction(){
return false;
} //特权/公有方法和属性
return {
publicProperty: true,
publicMethod : function(){
privateVariable++;
return privateFunction();
}
};
}();
以这种模式创建的每个单例都是Object的实例,因为最终要通过一个对象字面量来表示它。单例通常作为全局对象存在,不会将它传递给一个函数,不会使用instanceOf来检查其对象类型
增强的模块模式
在返回对象之前加入对其增强的代码。适合的场景是单例必须是某种类型的实例,还必须添加某些属性或方法对其增强。
var singleton = function(){ //私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
} //创建对象
var object = new CustomType();
//添加特权/公有属性和方法
object.publicProperty = true; object.publicMethod = function(){
privateVariable++;
return privateFunction();
}; //返回这个对象
return object;
}();
引用:
《JavaScript高级程序设计中文版》
最新文章
- StaticPagedList
- 关于网络爬虫项目的项目建议(NABCD)
- mongodb 主从服务器
- C++获取进程号及窗口
- uva 10912
- 动态缓存技术之CSI,SSI,ESI
- CefSharp开源库的使用(一)
- javascript 中caller,callee,call,apply 的概念[转载]
- Qt for Windows:使用WinPcap开发高性能UDP服务器
- TComponent明明实现了IDispatch接口,但是却不加上声明,难道是因为FVCLComObject实体对象不存在?
- [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
- SSO单点登录原理
- perl 递归删除目录和目录中的文件
- Linux redhat 7 进入单用户模式
- [原]openstack-kilo--issue(十八) Error parsing template file: Template format version not found.
- 一篇对OAuth2.0开发实例的介绍
- 【Django】关于scss 的安装
- iOS图片设置圆角性能优化
- 基于OpenGL编写一个简易的2D渲染框架-01 创建窗口
- Android Studio Run 'app'安装APK到设备的过程
热门文章
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
- P1137 旅行计划-----洛谷
- xcode升级到8.1
- VUE2.0实现购物车和地址选配功能学习第一节(来源--慕课网河畔一角)
- .NET中利用反射来实现自动映射两个对象中的数据成员
- 转 jquery怎么在header中设置请求信息
- 翻译:使用 Redux 和 ngrx 创建更佳的 Angular 2
- maven构建maven-project和maven-module
- Vue学习之路---No.2(分享心得,欢迎批评指正)
- npm学习总结