`
stationxp
  • 浏览: 17313 次
社区版块
存档分类
最新评论

Java程序员的JavaScript学习笔记(4——闭包/getter/setter)

 
阅读更多

计划按如下顺序完成这篇笔记:

  1. 理念。
  2. 属性复制和继承。
  3. this/call/apply。
  4. 闭包/getter/setter。
  5. prototype。
  6. 面向对象模拟。
  7. jQuery基本机制。
  8. jQuery选择器。
  9. jQuery工具方法。
  10. jQuery-在“类”层面扩展。
  11. jQuery-在“对象”层面扩展。
  12. jQuery-扩展选择器。
  13. jQuery UI。
  14. 扩展jQuery UI。

这是笔记的第4篇,聊聊闭包/getter/setter,看看JavaScript中的变量作用域和实现封装的方法。


作者博客:http://blog.csdn.net/stationxp

作者微博:http://weibo.com/liuhailong2008

转载请取得作者同意



1、闭包

闭包是JavaScript一项简单实用的语言特性。通过闭包:
弥补了函数没有public/private等访问访问权限控制符的缺陷,保护了函数内部变量的安全。
使得函数对象在作为参数传递时,不仅仅传递运算逻辑,同时也传递了相关变量。
使得函数“类”的不同实例,独享自己的属性。
下面逐个来看。

1.1、保护私有变量

1.1.1、原理

闭包最主要的特性是:当函数作为返回值时,连同函数定义时的环境(包括函数外部,函数可以访问到的变量)一起返回,确保这些变量不因其依附的对象销毁而被销毁。
有点儿绕,具体什么意思呢?看下面的代码:
// 代码段1
function UiObject() {
var childCount = 0; // 函数内部变量,
return 0;
}

var funcReturnValue = UiObject(); // 调用函数,返回0
console.log(UiObject.childCount); // 输出:undefined,由于函数调用完成,内部变量已经被销毁

childCount随着UiObject函数的调用结束而销毁,从另一个角度看,保护了函数内部的变量。
在这个基础上,如果我们有一种办法可以确保函数的内部变量不被销毁,而且提供方法对其访问操作,也就实现了通过public方法访问 private 变量。
代码如下:
// 代码段2
function UiObject() {
var childCount = 0; // 函数内部变量
function getChildCount(){
childCount = 6;
return childCount;
}
return getChildCount;
}
var funcReturnFObject = UiObject(); // 调用函数,返回 getChildCount 函数,返回值是一个闭包
console.log(funcReturnFObject()); // 输出:6
下面我们就看看,如果利用闭包的这一特性实现对私有属性的保护。


1.1.2、语法

在代码段2的基础上改进,代码段3展示的代码,可以同时提供多个方法,对私有属性访问。
//代码段3
function UiObject() {
var childCount = 0; // 函数内部变量

return {
getChildCount : function (){
return childCount;
},
setChildCount : function (cnt){
childCount = cnt;
}
};
}

var o = UiObject(); // 调用函数,返回 getChildCount 函数,返回值是一个闭包
o.setChildCount(6);
console.log(o.getChildCount()); // 输出:6

思考: 如果 var childCount = 0 ; 改为 this.childCount = 0; 呢?
我们之前研究过this,“ this.childCount = 0; ”语句是将childCount附加为调用者的属性,this.childCount的将生命周期与调用者相同。这与闭包不冲突。

代码段3还可以写成代码段4的形式。

// 代码段4
function UiObject() {
var childCount = 0; // 函数内部变量
this.setChildCount = function(cnt){
childCount = cnt;
};
this.getChildCount = function(){
return childCount;
};
}

var ui = new UiObject(); // 调用函数,返回retObj
console.log(ui.childCount); // 输出:undefined,由于函数调用完成,局部变量已经被销毁
ui.setChildCount(3); // 由于闭包的作用,ui仍然保存着变量childCount,并对其操作
console.log(ui.getChildCount()); // 输出:3

“this.setChildCount = function(cnt){ childCount = cnt; };” 这个语句相当于在UiObject内部定义了函数并“传递”了给ui对象。同样产生了闭包。

1.2、传递函数时,同时传递上下文

通过上面的例子,我们已经看到了这点特性。
在具体的应用场景中可对其大加利用。

1.3、不同实例,独享自己的变量

我们已经知道了,函数在传递过程中,会产生一个闭包。对于同一方法产生的闭包,是相同的,还是为每次传递创建了不同的拷贝呢?
看下面的代码:
//代码段5
function UiObject() {
var childCount = 0; // 函数内部变量

return {
getChildCount : function (){
return childCount;
},
setChildCount : function (cnt){
childCount = cnt;
}
};
}

var ui1 = UiObject();
var ui2 = UiObject();

ui1.setChildCount(1);
ui2.setChildCount(2);

console.log(ui1.getChildCount()); // output : 1
console.log(ui2.getChildCount()); // output : 2

每次生成闭包是不同的拷贝。

思考:对比Java,加深理解。



2、getter/setter


JavaScript
//代码段6
var uiPanel ={
_type : 'Panel',
_width : -1,
_height: -1,

get type(){ return this._type;},

get width(){ return this._width; },
set width(v){this._width = v;},

get height(){ return this._height; },
set height(v){this._height = v;}
};

uiPanel.type = 'TextField'; // does not work
console.log('type:'+uiPanel.type); // ouput : type:Panel

uiPanel.width = 800; //
console.log('width:'+uiPanel.width); // ouput : width:800

语法上越发有面向对象的范儿了。
除了在定义时通过set/set关键字控制属性的读写权限。还可以在运行期通过 Object.defineProperty()函数动态添加属性,并提供更精细的控制。
代码如下(以下代码均未经实验):
var o = {};
Object.defineProperty(o,'propName',{
value:1, //属性的值,也可以通过 get:function(){retun x;}的方法设定
writeable:true,//是否可以通过o.propName = newValue ; 的方法设置属性的值
enumerable:false,//是否可以通过被枚举
configurable:true//是否可以通过defineProperty配置
});
另外,还有一系列API可以完成对属性的配置、检测。如下:
Object.getOwnPropertyDescriptor{{x:1},"x"}
Object.keys(obj); // 获得对象上所有可枚举的“实例属性”
Object.getOwnPropertyNames(obj) ;//获得对象上所有的“实例属性”
obj.hasOwnProperty(‘id’); //只要该对象obj拥有属性id, 无论id是否可枚举,都返回true


3、小结

当大多数人已经习惯了面向对象的思维和方法,语言就要从特性方面予以满足,这不合理,也不美。但世界就是如此不完美。

JavsScript天生丽质,非要把她改造成机甲战士,那以后谁来负责倾国倾城呢?

ECMAScript 5不是革命性创新,也不是救命稻草这个世界本来可以更好的。




分享到:
评论

相关推荐

    尚硅谷——JavaScript闭包

    JavaScript闭包 JavaScript闭包 JavaScript闭包 JavaScript闭包

    Java闭包 Java闭包

    JSR-335 将闭包引入了 Java 。闭包在现在的很多流行的语言中都存在,例如 C++、C# 。闭包允许我 们创建函数指针,并把它们作为参数传递。在这篇文章中,将粗略的看一遍Java8的特性,并介绍 Lambda表达式。而且将试...

    深入理解javascript原型和闭包

    深入理解javascript原型和闭包(01)——一切都是对象 深入理解javascript原型和闭包(02)——函数和对象的关系

    JavaScript闭包

    Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态语言C/C++的程序员来说是一个新的语言特性。本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ...

    JavaScript闭包函数

    闭包是ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包。闭包的创建相对容易,人们甚至会在不经意间创建闭包,但这些无意创建的闭包却存在潜在的危害,尤其是在比较常见的浏览器环境下...

    深度探讨javascript函数的原型链和闭包

    深度探讨javascript函数的原型链和闭包

    javascript闭包详解中文word版

    Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态语言C/C 的程序员来说是一个新的语言特性。本文将以例子入手来介绍Javascript闭包的语言特性,并结合...

    javascript笔记之匿名函数和闭包.docx

    javascript笔记之匿名函数和闭包.docx

    浅析javascript语言中的函数闭包现象.pdf

    浅析javascript语言中的函数闭包现象.pdf

    深入理解_JavaScript_闭包

    理解 JavaScript 闭包 要成为高级 JavaScript 程序员,就必须理解闭包

    理解_JavaScript_闭包

    本文结合 ECMA 262 规范详解了闭包的内部工作机制,让 JavaScript 编程人员对闭包的理解从“嵌套的函数”深入到“标识符解析、执行环境和作用域链”等等 JavaScript 对象背后的运行机制当中,真正领会到闭包的实质。

    JavaScript 中级笔记 第四章 闭包

    前面已经讲解了 引用,函数重载,作用域和上下文,接下来,讲解JavaScript中另一个重要的知识——闭包。

    JavaScript_Core_-_V0.pdf

    JavaScript_Core 闭包/柯里化/

    javascript 闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

    Javascript 闭包完整解释

    Javascript 闭包完整解释

    【JavaScript源代码】详解JavaScript闭包问题.docx

    详解JavaScript闭包问题  闭包是纯函数式编程语言的传统特性之一。通过将闭包视为核心语言构件的组成部分,JavaScript语言展示了其与函数式编程语言的紧密联系。由于能够简化复杂的操作,闭包在主流JavaScript库...

    【JavaScript源代码】js闭包和垃圾回收机制示例详解.docx

    js闭包和垃圾回收机制示例详解  目录 前言 正文  1.闭包  1.1闭包是什么?  1.2闭包的特性 1.3理解闭包  1.4闭包的主要实现形式  1.5闭包的优缺点  1.6闭包的使用  2.垃圾回收机制 总结  前言  正文  ...

    凸多边形闭包算法(相对投影法)

    matlab求凸多边形闭包/相对投影法/含matlab源文件

    深入理解JavaScript系列(16) 闭包(Closures)

    介绍 本章我们将介绍在JavaScript里大家经常来讨论的话题 —— 闭包(closure)。闭包其实大家都已经谈烂了。尽管如此,这里还是要试着从理论角度来讨论下闭包,看看ECMAScript中的闭包内部究竟是如何工作的。 正如...

    scope-chains-closures, Javascript作用域链和闭包 workshop.zip

    scope-chains-closures, Javascript作用域链和闭包 workshop 范围链和闭包 workshop正在启动$ npm install -g scope-chains-closures$ scope-chains-closures # or, shorter: sccjs使用箭头

Global site tag (gtag.js) - Google Analytics