javascript高级程序设计笔记-第七章(函数表达式)
2016-03-02 17:16
573 查看
一、递归
递归函数是在一个函数通过名字调用自身的情况下构成的function factorial(num) { if (num <= 1) { return 1; } else { return num * factorial(num-1); } }
但是将此函数赋值给另一个函数时会出错
var anotherFactorial = factorial; factorial = null; alert(anotherFactorial(4)); //报错
使用arguments.callee
function factorial(num) { if (num <= 1) { return 1; } else { return num * arguments.callee(num-1); } } var anotherFactorial = factorial; factorial = null; alert(anotherFactorial(4)); //24
但是arguments.callee在严格模式下会导致错误
所以严格模式下,使用命名函数表达式
var factorial = (function f(num) { if (num <= 1) { return 1; } else { return num * f(num-1); } }); //创建一个名为f()的命名函数表达式,然后将其赋值给变量factorial
二、闭包
闭包是有权访问另一个函数作用域中的变量的函数,通常是通过在一个函数内部创建另一个函数来创建闭包function compare(value1, value2) { if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } } var result = compare(5, 10);
下图是compare()函数执行时的作用域链
一般当函数执行完毕后,局部活动对象就会被销毁,但是闭包不是,当creatComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但是它的活动对象仍然会留在内存中;直到匿名函数被销毁后,它的活动对象才会被销毁
function creatComparisonFunction(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 = creatComparisonFunction("name"); //调用函数 var result = compareNames({name: "Nicholas"}, {name: "Greg"});
1、闭包与变量
副作用:闭包只能取得包含函数中任何变量的最后一个值function createFunctions() { var result = new Array(); for (var i = 0; i < 10; i++) { result[i] = function() { return i; }; } return result; }
这个函数会返回一个数组,表面上看,似乎每个函数都应该返回自己的索引值,实际上每个函数都返回10
可以定义一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。而在这个匿名函数内部,创建一个闭包
function createFunctions() { var result = new Array(); for (var i = 0; i < 10; i++) { result[i] = function(num) { return function() { return num; }; }(i); } return result; }
2、关于this对象
在全局函数中,this等于window,当函数被作为某个对象的方法调用时,this等于那个对象。匿名函数的执行环境具有全局性,其this通常指向window。
var name = "the window"; var object = { name: "my object", getNameFunc: function() { return function() { return this.name; }; } }; alert(object.getNameFunc()()); //the window
把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象
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() { //这里是块级作用域 })();
将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式,紧随其后的另一对圆括号会立即调用这个函数
function() { //这里是块级作用域 }(); //报错 //函数声明后面不能跟圆括号,而函数表达式后面可以跟圆括号
如果只是临时需要一些变量,就可以使用私有作用域
function outputNumbers() { (function() { for (var i = 0; i < 10; i++) { console.log(i); //0,1,2,3,4,5,6,7,8,9 } })(); console.log(i); //报错 } outputNumbers();
这种技术通常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数
四、私有变量
任何在函数中定义的变量,都可以认为是私有变量。私有变量包括函数的参数、局部变量和函数内部定义的其他函数特权方法:有权访问私有变量和私有函数的共有方法
方法是在构造函数中定义特权方法
function MyObject() { var privateVariable = 10; function privateFunction() { return false; } //特权方法 this.publicMethod = function() { privateVariable ++; return privateFunction(); }; } //变量privateVariable和函数privateFunction()只能通过特权方法publicMethod()来访问
可以利用私有和特权成员,隐藏那些不应该被直接修改的数据
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
1、静态私有变量
(function MyObject() { //私有变量和私有函数 var privateVariable = 10; function privateFunction() { return false; } //构造函数 MyObject = function() {}; //特权方法 MyObject.prototype.publicMethod = function() { privateVariable ++; return privateFunction(); }; })();
2、模块模式
为单例创建私有变量和特权方法,单例指只有一个实例的对象var singleton = function() { //私有变量和函数 var var privateVariable = 10; function privateFunction() { return false; } //特权方法和属性 return { publicProperty: true, publicMethod: function() { privateVariable ++; return privateFunction(); } }; }();
如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有数据的方法,就可以使用模块模式
3、增强的模块模式
适合那些单例必须是某种类型的实例,同时还必须添加某些属性和方法对其加以增强的情况var singleton = function() { //私有变量和函数 var var privateVariable = 10; function privateFunction() { return false; } //创建对象 var object = new CustomType(); //添加特权方法和属性 object.publicProperty = true; object.publicMethod = function() { privateVariable ++; return privateFunction(); }; //返回这个对象 return object; }();
相关文章推荐
- 文本框只允许输入数字.net/javascript
- 如何销毁js的变量啊?
- JSON解析---初识
- js 搜索关键字,文章中关键字高亮显示
- jsp常用动作
- 接收时间戳model [JsonConverter(typeof(UnixDateTimeConverter))]
- js中Math.round、parseInt、Math.floor和Math.ceil小数取整总结
- js如何获取选中的单选框
- javascript 之小白学习指南 闭包的详解
- js Math 对象的方法
- jsp页面不乱码,外部引用的js弹出对话框乱码
- js数字舍入误差以及解决方法
- 【读书笔记】JavaScript图片库
- JSP脚本中的9个内置对象
- js读取解析JSON类型数据
- js倒计时代码 适合于本月促销-倒计时代码
- js 对闭包的理解
- 关于日期的js相关操作
- js 签到用日历
- js动态表格追加行