未加星标

《javascript权威指南》第八章8.6章节

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二05 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏
在同一个作用域链中定义多个闭包,这些闭包可以共享同样的私有变量

例子4:闭包实现属性存取器方法getter和setter

将counter函数的代码改一下,这里的私有变量(或者叫私有状态)的实现利用了闭包

function counter(n) { //参数n是一个私有变量,写在这里可以直接初始化变量 return { //直接返回了2个方法,并且这2个方法是getter和setter get count(){ //直接默认会调用getter方法,会将参数n直接加一并返回 return n++; }, set count(m){ if(m >= n){ n = m ; //这里可以看到私有变量n 也可以被改变,因为这个私有变量是在函数counter 里面共同拥有的 }else{ throw Error("count can only be set to a larger value"); } } } } var c = counter(1000); //默认会调用getter方法(即get XXXXX),而如果是赋值的话,那么就会调用setter方法(即set XXXXX) console.log(c.count);//结果1000,调用getter方法 console.log(c.count);//结果1001,调用getter方法,可以看到加一了 console.log(c.count = 2000);//结果2000,调用setter方法,由于之前n已经被赋值过了,因为之前传了n=1000的参数,所以现在调用setter方法的时候,可以用当前的赋值跟n对比,当前是2000,n是1000,所以n = m console.log(c.count);//结果2000 console.log(c.count = 2000);//结果Error,因为之前改变了n的值为2000,所以再次传入的参数是2000的话,那么就触发了else判断,返回错误

例子5:利用闭包实现的私有属性存取器方法

//这个函数给对象o增加了属性存取器方法 //方法名称为get<name>和set</name><name>,如果提供了一个判断函数,那么setter方法就会用它 //来检测参数的合法性,然后再存储它 function addPrivateProperty(o,name,predicate) { //第四点 var value; // 第一点 o["get"+name] = function () { // 第二点 return value; }; o["set"+name] = function (v) { // 第三点 if(predicate && !predicate(v)){ //这里的判断写法比较有意思,函数存在并且返回值不是false的情况下 throw Error ("set" + name + ":invalid value " + v); }else{ value = v; } }; } var o = {}; addPrivateProperty(o,"Name",function (x) { // 第五点 return typeof x == "string"; }); o.setName("Frank"); // 第六点 console.log(o.getName()); // 第七点 o.setName(2); //第八点 初始化变量value,作为一个属性的值,默认情况下这是空值,除非setter方法存储 getter方法直接返回值,而这个值是靠setter方法存储的 setter方法,这个v其实一个默认的形参,当使用setter方法的时候,会进行传入 函数addPrivateProperty支持3个参数,第一个是对象,第二个是getter和setter的组合参数,为了创建getName和setName这样的命名的getter和setter方法,第三个参数是一个函数,目前看不出来,需要看里面才知道,因为setter里面有这个函数的调用 这里是初始化addPrivateProperty,确定好他的形参的类型,这里是确定了一个o对象,一个Name的字符串,和一个函数,这个函数里面是判断传参是否是string的 这里直接使用setter,因为之前确定了Name作为第二个参数,并且和set组合起来,所以o对象就有了setName方法,并且这个方法传入一个Frank的字符串,这个参数其实就是v,自动创建变量v 直接调用getter,组合起来就有了getName这个方法,自动方法刚才被setter设置的value值Frank 这里直接调用setter,但是传入的是一个2,通过之前设置的判断函数来将其抛出Error 下面这个是不使用共享变量的 function constfunc(v) { return function () { //第一点 return v; }; } var funcs = []; for (var i = 0; i < 10; i++) { funcs[i] = constfunc(i); //第二点 } console.log(funcs[5]()); //第三点 这里直接返回一个函数 每一个funcs数组元素都被复制一个constfunc返回的函数,参数是跟数组的的下标一样 这里需要注意的是,funcs[5]这里的值是一个函数而不是一个变量,是constfunc(5),即function(){return v},v是传入的参数,现在v是5,然后加上()进行函数执行,所以结果是5

可以看到每个闭包是独立的,变量也是独立的

反面教材是

function constfuncs() { var funcs = []; for(var i = 0;i<10;i++){ funcs[i] = function () { return i; } } return funcs; } var funcs = constfuncs(); console.log(funcs[5]()); //结果是10 因为这里虽然创建了10个闭包,但是这些闭包都是在同一个函数中调用的,因此他们共享变量i 因为执行了for循环,i会从0开始递增,直到i=10停止,所以i会等于10,另外因为for循环的关系,数组funcs有10个元素,每个元素都有一个函数,这个函数都会返回i的值,即funcs[0] = function(){return i;},funcs[1] = function(){return i;}.....如此类推,因为i共享的关系,而i又等于10 ,所以这个数组的所有的值都会是10 这里的关键在于,i是共享的,所以i的值统一,闭包的作用域链是在创建的时候建立的,这个作用域链如果能读取共享变量的话,那么能实现变量的共享 每个函数调用都包含一个this值

闭包在外部函数里是无法访问this的,除非外部函数将this转存为一个变量

var self = this; //将this保存在一个变量中,以便嵌套的函数能够访问他

arguments也一样,闭包无法直接访问外部函数的参数数组,除非外部函数将参数数组保存到另外一个变量中

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: 变量其实
分页:12
转载请注明
本文标题:《javascript权威指南》第八章8.6章节
本站链接:http://www.codesec.net/view/479666.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(52)