JS编程建议——61:使用闭包跨域开发

建议61:使用闭包跨域开发
闭包是指词法表示包括不必计算的变量的函数,闭包函数能够使用函数外定义的变量。闭包结构有以下两个比较鲜明的特性。
(1)封闭性
外界无法访问闭包内部的数据,如果在闭包内声明变量,外界是无法访问的,除非闭包主动向外界提供访问接口。
(2)持久性
对于一般函数来说,在调用完毕之后,系统会自动注销函数,而对于闭包来说,在外部函数被调用之后,闭包结构依然保存在系统中,闭包中的数据依然存在,从而实现对数据的持久使用。例如:
function f( x ){

var a = x;
var b = function(){
    return x;
}
return b;

}
var c = f( 1 );
alert(c()); //1。调用闭包函数
在上面示例中,首先在函数f结构体内定义两个变量,分别存储参数和闭包结构,而闭包结构中寄存着参数值。当调用函数f之后,函数结构被注销,它的局部变量也随之被注销,因此变量a中存储的参数值也随之丢失。但由于变量b存储着闭包结构,因此闭包结构内部的参数值并没有被释放,在调用函数之后,依然能够从闭包结构中读取到参数值。
从结构上分析,闭包函数与普通函数没有什么不同,主要包含以下类型的标识符:
函数参数(形参变量)。
arguments属性。
局部变量。
内部函数名。
this(指代闭包函数自身)。
其中this和arguments是系统默认的函数标识符,不需要特别声明。这些标识符在闭包体内的优先级是(其中左侧优先级大于右侧):this → 局部变量 → 形参 → arguments → 函数名。
下面以一个经典的闭包示例来演示上述抽象描述:
1 function f(x){ // 外部函数
2 var a = x; // 外部函数的局部变量,并把参数值传递给它
3 var b = function(){ // 内部函数
4 return a; // 访问外部函数中的局部变量
5 };
6 a++; // 访问后,动态更新外部函数的变量
7 return b; // 内部函数
8 }
9 var c = f(5); // 调用外部函数,并赋值
10 alert(c()); // 调用内部函数,返回外部函数更新后的值6
演示步骤说明如下:
第1步,程序预编译之后,从第9行开始解析执行,创建上下文环境,创建调用对象,把参数、局部变量、内部的函数转换为对象属性。
第2步,执行函数体内代码。在第6行执行局部变量a的递加运算,并把这个值传递给对象属性a,内部函数动态保持与局部变量a的联系,同时更新自己内部调用变量的值。
第3步,外部函数把内部函数返回给全局变量c,实现内部函数的定义,此时c完全继承了内部函数的所有结构和数据。
第4步,外部函数返回后(即返回值后调用完毕)会自动销毁,内部的结构、标识符和数据也随之丢失。
第5步,执行第10行代码命令,调用内部函数,此时返回的是外部函数返回时(销毁之前)保存的变量a所存储的最新数据值,即返回6。
如果没有闭包函数的作用,那么这种数据寄存和传递就无法得以实施。例如:
1 function f(x){
2 var a = x;
3 var b = a; // 直接把局部变量的值传递给局部变量b
4 a++
5 return b; //局部变量b
6 }
7 var c = f(5);
8 alert(c); //值为5
通过上面的示例可以很直观地看到,在没有闭包函数的辅助下,第8行代码执行后返回值并没有与外部函数的局部变量a最后更新的值保持一致。
闭包在程序开发中具有重要的价值。例如,使用闭包结构能够跟踪动态环境中数据的实时变化,并即时存储。
function f(){

var a = 1;
var b = function(){
    return a;
}
a++;
return b;

}
var c = f();
alert(c()); //返回2,而不是1
在上面示例中,闭包中的变量a存储的值并不是对上面行变量a的值的简单复制,而是继续引用外部函数定义的局部变量a中的值,直到外部函数f调用返回。闭包不会因为外部函数环境的注销而消失,会始终存在。例如:

var a = 1;
b = function(){
    alert( a );
}
c = function(){
    a ++ ;
}
d = function( x ){
    a = x;
}

}

按钮1:(f( ))()

按钮2:(b = function(){alert( a );})()

按钮3:(c = function(){a ++ ;})()

按钮4:(d = function( x ){a = x; }) (100)

在上面示例中,在函数f中定义了3个闭包函数,它们分别指向并寄存局部变量a的值,并根据不同的操作动态跟踪变量a的值。当在浏览器中预览时,首先应该单击“按钮1”,调用函数f,生成3个闭包,3个闭包同时指向局部变量a的引用,因此,当函数f返回时,这3个闭包函数都没有被注销,变量a由于被闭包引用而继续存在。这时,如果直接单击“按钮2”和“按钮4”,那么会由于没有在系统中生成闭包结构,而弹出编译错误。单击“按钮3”将动态递增变量a的值,此时如果单击“按钮2”,则会弹出提示值2。如果单击“按钮4”,则向变量a传递值100,将动态改变闭包中寄存的值,此时如果单击“按钮2”,则会弹出提示值100。

时间: 2024-10-28 12:01:50

JS编程建议——61:使用闭包跨域开发的相关文章

浅谈js中几种实用的跨域方法原理详解_javascript技巧

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作是不同的域. 下表给出了相对http://store.company.com/dir/page.html同源检测的结果: 要解决跨域的问题,我们可以使用以下几种方法: 一.通过jsonp跨域 在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的.但是,在页面上引入不同

js中window.opener方法的跨域问题分析

最近公司网站登陆加入了第三方登陆.可以用QQ直接登陆到我们网站,在login页面A中点QQ登陆时,调用了一个window.open文件打开一个login页窗口B,登陆后callback地址回调成功后,需要关闭当前window.open打开的login小窗口B,再将打开这个小窗口的原窗口页(A)刷新显示正确状态. 这时就用到了这个方法: window.opener.location.reload() 与 window.opener.location.href=window.opener.locat

js中几种实用的跨域方法原理详解

1.这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作是不同的域. (1)下表给出了相对http://store.company.com/dir/page.html同源检测的结果: 要解决跨域的问题,我们可以使用以下几种方法: 一.通过jsonp跨域 在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的.但是,在页面

Js中启用CORS实现Ajax跨域请求

启用CORS实现Ajax跨域请求 某年某月的一天,需要实现这样一个需求,在当前站点中用ajax发送一个请求到另一个站点获取数据,b.com   ->    s.com,刚开始以为没什么,不就一条请求嘛,立马就写了出来,结果出现一个错误200的请求,还有一个提示信息: 20141020162144 这是什么情况,于是找度娘问了起来,大概的结果如下(部分文字直接拿过来的): 跨域是我在日常面试中经常会问到的问题,这词在前端界出现的频率不低,主要原因还是由于安全限制(同源策略, 即JavaScript

JS编程建议——62:在循环体和异步回调中慎重使用闭包

建议62:在循环体和异步回调中慎重使用闭包闭包在开发中具有重要的应用价值,由于闭包具有持久性,生成的闭包不会立即被销毁,因此它会持续占用系统资源.如果大量使用闭包,将会造成系统资源紧张,甚至导致内存溢出等错误.另外,闭包在回调函数中会带来负面影响,因此在使用时应该慎重.下面的示例利用闭包来存储变量所有变化的值.function f( x ){ var a = []; for ( var i = 0; i < x.length; i ++ ){ var temp = x[i]; a.push( f

JS编程建议——65:比较函数的惰性求值与非惰性求值

建议65:比较函数的惰性求值与非惰性求值在JavaScript中,使用函数式风格编程时,应该对于表达式有着深刻的理解,并能够主动使用表达式的连续运算来组织代码.1)在运算元中,除了JavaScript默认的数据类型外,函数也作为一个重要的运算元参与运算.2)在运算符中,除了JavaScript的大量预定义运算符外,函数还作为一个重要的运算符进行计算和组织代码.函数作为运算符参与运算,具有非惰性求值特性.非惰性求值行为自然会对整个程序产生一定的负面影响.先看下面这个示例:var a = 2;fun

JS编程建议——2:正确辨析JavaScript句法中的词、句和段

建议2:正确辨析JavaScript句法中的词.句和段JavaScript语法包含了合法的JavaScript代码的所有规则和特征,它主要分为词法和句法.词法包括字符编码.名词规则.特殊词规则等.词法侧重语言的底层实现(如语言编码问题等),以及基本规则的定义(如标识符.关键字.注释等).它们都不是最小的语义单位,却是构成语义单位的组成要素.例如,规范字符编码集合.命名规则.标识符.关键字.注释规则.特殊字符用法等.句法定义了语言的逻辑和结构,包括词.句和段的语法特性,其中段体现逻辑的结构,句表达

JS编程建议——3:减少全局变量污染

建议3:减少全局变量污染定义全局变量有3种方式:在任何函数外面直接执行var语句. var f = 'value'; 直接添加一个属性到全局对象上.全局对象是所有全局变量的容器.在Web浏览器中,全局对象名为window. window.f = 'value'; 直接使用未经声明的变量,以这种方式定义的全局变量被称为隐式的全局变量. f = 'value'; 为方便初学者在使用前无须声明变量而有意设计了隐式的全局变量,然而不幸的是忘记声明变量成了一个非常普遍的现象.JavaScript的策略是让

JS编程建议——74:使用高阶函数

建议74:使用高阶函数高阶函数作为函数式编程众多风格中的一项显著特征,经常被使用.实际上,高阶函数即对函数的进一步抽象.高阶函数至少满足下列条件之一:接受函数作为输入.输出一个函数. 在函数式语言中,函数不但是一种特殊的对象,还是一种类型,因此函数本身是一个可以传来传去的值.也就是说,某个函数在刚开始执行的时候,总可以送入一个函数的参数.传入的参数本身就是一个函数.当然,这个输入的函数相当于某个函数的另外一个函数.当函数执行完毕之后,又可以返回另外一个新的函数,这个返回函数取决于return f