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中的变量作用域和实现封装的方法。

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不是革命性创新,也不是救命稻草,这个世界本来可以更好的。

时间: 2024-12-19 03:20:56

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

Java程序员的JavaScript学习笔记 (目录)

终于完结了,历时半个月. 内容包括: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源码级解析. jQuery EasyUI源码级解析. Java程序员的JavaScript学习笔记(1——理念) Java程序员的JavaScript学习笔记(2——属性复制和继承) Java程序员的JavaScript学习笔记(3——this/call/apply) Java程序员的JavaScript学习笔记(4——this/闭包/getter/setter) Java

Java程序员的JavaScript学习笔记(14——扩展jQuery UI)

计划按如下顺序完成这篇笔记: Java程序员的JavaScript学习笔记(1--理念) Java程序员的JavaScript学习笔记(2--属性复制和继承) Java程序员的JavaScript学习笔记(3--this/call/apply) Java程序员的JavaScript学习笔记(4--this/闭包/getter/setter) Java程序员的JavaScript学习笔记(5--prototype) Java程序员的JavaScript学习笔记(6--面向对象模拟) Java程序员

Java程序员的JavaScript学习笔记(汇总目录)

终于完结了,历时半个月. 内容包括: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源码级解析. jQuery EasyUI源码级解析. Java程序员的JavaScript学习笔记(1--理念) Java程序员的JavaScript学习笔记(2--属性复制和继承) Java程序员的JavaScript学习笔记(3--this/call/apply) Java程序员的JavaScript学习笔记(4--this/闭包/getter/setter) Java

Java程序员的JavaScript学习笔记(5——prototype和Object内置方法)

计划按如下顺序完成这篇笔记: 理念. 属性复制和继承. this/call/apply. 闭包/getter/setter. prototype. 面向对象模拟. jQuery基本机制. jQuery选择器. jQuery工具方法. jQuery-在"类"层面扩展. jQuery-在"对象"层面扩展. jQuery-扩展选择器. jQuery UI. 扩展jQuery UI. 这是笔记的第5篇,聊聊prototype.内置的Object对象和Object对象的属性和

Java程序员的JavaScript学习笔记(2——属性复制和继承)

计划按如下顺序完成这篇笔记: 理念. 属性复制和继承. this/call/apply. this/闭包/getter/setter. prototype. 面向对象模拟. jQuery基本机制. jQuery选择器. jQuery工具方法. jQuery-在"类"层面扩展. jQuery-在"对象"层面扩展. jQuery-扩展选择器. jQuery UI. 扩展jQuery UI. 这是笔记的第2篇,聊聊属性复制和继承的事情.非常基础,同样,也非常重要. 一切皆

Java程序员的JavaScript学习笔记(6——面向对象模拟)

计划按如下顺序完成这篇笔记: 理念. 属性复制和继承. this/call/apply. 闭包/getter/setter. prototype. 面向对象模拟. jQuery基本机制. jQuery选择器. jQuery工具方法. jQuery-在"类"层面扩展. jQuery-在"对象"层面扩展. jQuery-扩展选择器. jQuery UI. 扩展jQuery UI. 这是笔记的第6篇,对前面5篇做一个总结,聊聊JavaScript在面向大型复杂任务时候,如

Java程序员的JavaScript学习笔记(7——jQuery基本机制)

计划按如下顺序完成这篇笔记: 理念. 属性复制和继承. this/call/apply. 闭包/getter/setter. prototype. 面向对象模拟. jQuery基本机制. jQuery选择器. jQuery工具方法. jQuery-在"类"层面扩展. jQuery-在"对象"层面扩展. jQuery-扩展选择器. jQuery UI. 扩展jQuery UI. 这是笔记的第7篇,聊聊jQuery基本机制,学习的同时,我们试图实现一个缩略版本的jQue

Java程序员的JavaScript学习笔记(3——this/call/apply)

计划按如下顺序完成这篇笔记: 理念. 属性复制和继承. this/call/apply. 闭包/getter/setter. prototype. 面向对象模拟. jQuery基本机制. jQuery选择器. jQuery工具方法. jQuery-在"类"层面扩展. jQuery-在"对象"层面扩展. jQuery-扩展选择器. jQuery UI. 扩展jQuery UI. 这是笔记的第3篇,聊聊JavaScript中的this,还有两种调用函数的特殊方式:cal

Java程序员的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)

计划按如下顺序完成这篇笔记: 1.    理念. 2.    属性复制和继承. 3.    this/call/apply. 4.    闭包/getter/setter. 5.    prototype. 6.    面向对象模拟. 7.    jQuery基本机制. 8.    jQuery选择器. 9.    jQuery工具方法. 10.    jQuery-在"类"层面扩展. 11.    jQuery-在"对象"层面扩展. 12.    jQuery-扩