javascript面向对象之闭包

学习javascript一段时间了,自己对闭包作出如下总结,如有某点不妥,请君指出,不胜感激!

要理解闭包,首先必须理解Javascript特殊的变量作用域。

变量的作用域无非就是两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量,而在函数外部无法读取函数内的局部变量。

注意点,函数内部声明变量的时候,一定要使用var命令。否则变为全局变量。

简而言之,闭包就是一个受到保护的变量空间。

闭包案例

functon(){
var num = Math.random;
return num; }
var res = foo();
在这不能直接访问函数内部变量num,只可以间接访问 var r1 = foo();
var r2 = foo();
alert(r1 + '\n'+ r2);
如果使用return返回函数内的数据,理论上不是访问一个数据,
因为在函数运行会分配内存空间,函数调用的时候,数据也会再次创建

若要解决以上问题,获得相同的数据如何操作

function (){
var num = Math.random();
return function (){ return num;
} } var fn = foo();//函数调用一次num就是唯一的
var r1 = fn();
var r2 = fn();
alert(r1 + '\n' +r2)
//fn是在一个在函数内定义的函数,那么在执行时候可以访问到上一级作用域中的num ,
因此在最外面,就可以间接访问唯一的num。此处就是用到了闭包,此次起到保护数据的我作用

函数的本质:Function的实例,也是对象。

执行一个函数,让函数返回对象

function Foo(){
var o = {num: 123};
return o;
}
var obj = Foo();
alert(obj.num);//123

在调用函数时,函数内部创建一个对象

o中存储着对象的引用,return是将o中的数据拷贝一份再返回

返回的结果被obj接收,此时obj存储的是对象的引用

执行一个函数,让函数返回一个函数

function Foo(){
var o = new Function('alert(123)');
return o;
}
var fn = Foo();
相当于var fn = new Functon('alert(123)');
alert(fn);//123

执行一个函数,让函数返回一个数组

function func(){
var m = Math.random();
var n = Math.random();
return [
function () { return m;}
function () { return n;} ]
}
// var fns = func();
// var m1 = fns[0]();
// var n1 = fns[1]();
// alert(m1 +','+ n1) ; // var m2 = fns[0]();
// var n2 = fns[1]();
// alert(m2 +','+ n2) ;

在以上两组数据中输出的结果是相同的,

数组的优点体现出数据的有序性 多个数据可以进行排序

但是在复杂数据中,数据的序号就不再有优势

可以用对象对以上函数改进

function func(){
var m = Math.random();
var n = Math.random();
return {
get_M: function (){ return m;},
get_N: function (){ return n;}
};
}
// var obj = func();
// var m1 =obj.get_M();
// var n1 = obj.get_N();
// alert(m1 +','+ n1) ;

闭包案例之调用一函数提供两个方法,对num进行赋值和读取
第一种写法

function Foo(){
var obj = new Object(); //这里也可以写成 var obj = {};??
var num;
obj.get_num = function(){
return num;
};
obj.set_num = function(v){
num = v; };
return obj; }
var o = Foo();
console.log(o.get_num());//undefined
console.log(o.set_num(11));//undefined
console.log(o.get_num(11));//11

第二种写法

function Foo() {
var num;
return {
get_num: function () {
return num;
},
set_num: function ( v ) {
num = v;
}
};
}
var o = Foo();
console.log( o.get_num() ); //undefined
console.log(o.set_num( 11 ));//undefined
console.log( o.get_num() );//11

这有一个对以上函数的变式

function Foo() {
var num;
return {
_num: num,//赋值操作
set_num: function ( v ) {
num = v;
}
};
}
//相当于下面函数
function Foo() {
var num;
var obj = {};
obj._num = num;//上面声明的num和此时的_num变量是不同的
obj.set_num = function ( v ) {
num = v;
};
return obj;
} var o = Foo();
console.log( o._num );  //undefined
console.log(o.set_num(11)); //undefined
console.log(o._num); //undefined 取不出数据

闭包的应用:实现私有数据和缓存数据

闭包案例之斐波那契数列

没使用闭包的函数式

var count = 0;
var fib = function (n){
count++;
if(n< 0)throw new Error('不允许出现负数');
if(n === 0||n === 1)return 1;
// return fib(n-1)+fib(n-2);
return arguments.callee(n-1) + arguments.callee(n-2);
} console.log(fib(16));
console.log(count);
//分别计算第1、2、4、8、16、32项对应的次数为1、3、9、67、3193、7049155

从以上计算的次数可以看出性能的损耗很严重,那么闭包可以在此解决的问题是已经运算过得数据缓存下来

var count = 0;
var fib = (function(){
var arr = [];
return function (n){
count++;
if(n < 0)throw new Error('不允许出现负数');
var res = arr[n];//缓存数据 判断有无数据
if(res !== undefined){
return res;
}
else {
if(n === 0||n ===1) {
res = 1;
}
else{
res = fib(n - 1)+fib(n - 2);
}
}
arr[n] = res;
return res;
}
})();
console.log(fib(100));
console.log(count);//199

第二种写法

var count = 0;
var fib = (function(){
var arr = [];
return function(n){
count++;
return feibo(arr,n);
}
})();
function feibo(arr,n){
if(n < 0)throw new Error("不允许出现负数");
var res = arr[n];
if(res != undefined){
return res;
}else{
if(n === 0 ||n === 1){
res = 1;
}else{
res = fib(n - 1) + fib(n - 2);
}
}
arr[n] = res;
return res;
}
console.log(fib(100));
console.log(count);

从上式可以看出闭包带来的好处;

拓展:谈到数据缓存也可以不用闭包,下面函数则与闭包无关

var fib = function ( n ) {
var res = fib[ n ]; // 先到函数名中取
if ( res !== undefined ) {
return res;
} else {
// 如果是 1 或 0 则将 1 返回给 res
// 否则递归结果交给 res; if ( n === 0 || n === 1 ) {
res = 1;
} else {
res = arguments.callee( n - 1 ) +
arguments.callee( n - 2 );
} fib[ n ] = res;
// 将计算的结果放到数组中, 那么下一次再计算的
// 时候可以直接拿来用, 就不用重新计算
fib.len++;//每次赋值完后
return res;
}
};
fib.len = 0;//给函数添加一个属性
console.log(fib(100));
console.log(fib.len)//101

javascript面向对象之闭包的更多相关文章

  1. 关于javascript面向对象之闭包

    要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量,而在函数外部无法 ...

  2. JavaScript面向对象,闭包内存图,闭包和作用域

    var i = 10; function test(){ var j; i=20; //未定义 function test(){ j='hello'; } console.log(test()); / ...

  3. JavaScript面向对象之闭包的理解

    首先了解一下什么是闭包,闭包是一个函数,通常被称为闭包函数或者绑定函数,该函数运行在一个特殊的环境里,该环境定义了一些本地变量,当该函数被调用时,仍可以使用这些本地变量. 当一个函数在不位于它所处的环 ...

  4. JavaScript面向对象(三)——继承与闭包、JS实现继承的三种方式

      前  言 JRedu 在之前的两篇博客中,我们详细探讨了JavaScript OOP中的各种知识点(JS OOP基础与JS 中This指向详解 . 成员属性.静态属性.原型属性与JS原型链).今天 ...

  5. JavaScript函数、闭包、原型、面向对象

    JavaScript函数.闭包.原型.面向对象 断言 单元测试框架的核心是断言方法,通常叫assert(). 该方法通常接收一个值--需要断言的值,以及一个表示该断言目的的描述. 如果该值执行的结果为 ...

  6. javascript(面向对象,作用域,闭包,设计模式等)

    javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...

  7. 闭包初体验 -《JavaScript面向对象编程指南》

    下面是我对闭包的理解:(把他们整理出来,整理的过程也是在梳理) 参考<JavaScript面向对象编程指南> 1.首先,在理解闭包之前: 我们首先应该清楚下作用域和作用域链 作用域:每个函 ...

  8. JavaScript学习笔记(三)——this、原型、javascript面向对象

    一.this 在JavaScript中this表示:谁调用它,this就是谁. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是一个动态的对象,根据调用的对象不同而发生变化, ...

  9. JavaScript学习总结(三)——this、原型、javascript面向对象

    一.this 在JavaScript中this表示:谁调用它,this就是谁. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是一个动态的对象,根据调用的对象不同而发生变化, ...

随机推荐

  1. 我在使用的Chrome插件

    首先本人为一名Android程序员,故下面的很多插件很多都是关于开发辅助相关的.当然还有涉及到其他方面的插件,比如社交,浏览,工具等.以下按照字母排序. 1.AdBlock The most popu ...

  2. XML学习经验实例总结2

    DTD约束 Book.dtd: <!ELEMENT 书架 (书+)> <!ELEMENT 书 (书名,价格,介绍)> <!ELEMENT 书名 (#PCDATA)> ...

  3. Matlab的parfor并行编程

    Matlab的parfor并行编程 通常消耗最多计算资源的程序往往是循环. 把循环并行化.或者优化循环体中的代码是最经常使用的加快程序执行速度的思路. Matlab提供了parforkeyword,能 ...

  4. Swift - 使用NSUserDefaults来进行本地数据存储

    NSUserDefaults适合存储轻量级的本地客户端数据,比如记住密码功能,要保存一个系统的用户名.密码.使用NSUserDefaults是首选.下次再登陆的时候就可以直接从NSUserDefaul ...

  5. html ui设计案例

    1.jquery特效:http://www.5icool.org 2. http://www.open-lib.com/Lib/1992.jsp

  6. GitHub上项目配置和导入eclispe的问题解决

    在github上下载的工程文件导入的时候总是遇到各种各样的问题,昨天晚上瞎忙一晚上查资料没搞定.早上找高手请教了一下,一起弄了好一会终于解决了,这里记录一下方法解决的具体方法步骤. 本方法适用于离线导 ...

  7. Jetty开发指导:HTTP Client

    介绍 Jetty HTTP client模块提供易用的API.工具类和一个高性能.异步的实现来运行HTTP和HTTPS请求. Jetty HTTP client模块要求Java版本号1.7或者更高,J ...

  8. javascript (二) 事件

    <script></script> 函数写法: function  fun_name(){ x=docment.getElementById("demo") ...

  9. 函数指针玩得不熟,就不要自称为C语言高手(函数指针是解耦对象关系的最佳利器,还有signal)

    记得刚开始工作时,一位高手告诉我说,longjmp和setjmp玩得不熟,就不要自称为C语言高手.当时我半信半疑,为了让自己向高手方向迈进,还是花了一点时间去学习longjmp和setjmp的用法.后 ...

  10. 新发现QWindow

    http://doc.qt.io/qt-5/qwindow.html#details 不知道该什么时候使用它?