`
Finder
  • 浏览: 27382 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

JavaScript面向对象程序设计(8): 优雅的封装还是执行的效率?

阅读更多

优雅的封装还是执行的效率?这是一个悖论。

 

优雅封装的程序看起来是那么的美妙:每个属性被隐藏在对象之后,你所能看到的就是这个对象让你看到的,至于它到底是怎么操作的,这个不需要你操心。

 

执行的效率就是另外一回事。就像是C语言和面向对象的C++之间的差别:C++很优雅,但是执行效率,无论是编译后的二进制代码还是运行期的内存的占用,都要比简单的C语言多出一截来。

 

这个问题在脚本语言中显得更加重要,因为JavaScript根本就是一种解释语言,解释语言的执行效率要比编译语言低很多。

 

1. 优雅的封装

 

我们先来看看变量封装。这里的变量不仅仅是属性,也包括函数。

 

前面已经说过,JavaScript中并没有类这个概念,是我们利用变量作用域和闭包“巧妙的模拟”出来的,这是一种优雅的实现。还是温故一下以前的代码:

 

function Person() {
    var id;
    var showId = function() {
        alert("My id is " + id);
    }
    this.getId = function() {
        return id;
    }
    this.setId = function(newId) {
        id = newId;
    }
}
var p = new Person();
p.setId(1000);
alert(p.id); // undefined
// p.showId(); error: function not defined
var p2 = new Person();
alert(p.getId == p2.getId); // false

 

我们很优雅的实现了私有变量——尽管是投机取巧的实现的。但是,这段代码又有什么问题呢?为什么两个对象的函数是不同的呢?

 

想一下,我们使用变量的作用域模拟出私有变量,用闭包模拟出公有变量,那么,也就是说,实际上每个创建的对象都会有一个相同的代码的拷贝!不仅仅是那个id,就连那些showId、getId 等函数也会创建多次。注意,考虑到JavaScript函数就是对象,就不会感到那么奇怪了。但是毫无疑问,这是一种浪费:每个变量所不同的只是自己的数据域,函数代码都是相同的,因为我们进行的是同一种操作。其他语言一般不会遇到这种问题,因为那些语言的函数和对象的概念是不同的,像Java,每个对象的方法其实指向了同一份代码的拷贝,而不是每个对象都会有自己的代码拷贝。

 

2. 去看效率

 

那种封装虽然优雅,但是很浪费。好在JavaScript是一种灵活的语言,于是,我们马上想到,把这些函数的指针指向另外的一个函数不就可以了吗?

 

function show() {
    alert("I'm a person.");
}
function Person() {
    this.show = show;
}
var p1 = new Person();
var p2 = new Person();
alert(p1.show == p2.show); // true

 

这个办法不错,解决了我们以前的那个问题:不同的对象共享了一份代码。但是这种实现虽然有了效率,可是却太不优雅了——如果我有很多类,那么岂不是有很多全局函数?

 

好在JavaScript中还有一个机制:prototype。还记得这个prototype吗?每个对象都维护着一个prototype属性,这些对象的prototype属性是共享的。那么,我们就可以把函数的定义放到prototype里面,于是,不同的对象不就共享了一份代码拷贝吗?事实确实如此:

 

function Person() {
}
Person.prototype.show = function() {
    alert("I'm a person.");
}
var p1 = new Person();
var p2 = new Person();
alert(p1.show == p2.show); // true

 

不过,这种分开定义看上去很别扭,那么好,为什么不把函数定义也写到类定义里面呢?

 

function Person() {   
    Person.prototype.show = function() {   
        alert("I'm a person.");   
    }   
}   
var p1 = new Person();   
var p2 = new Person();   
alert(p1.show == p2.show); // true   

 

实际上这种写法和上面一种没有什么不同:唯一的区别就是代码位置不同。这只是一个“看上去很甜”的语法糖,并没有实质性差别。

 

最初,微软的.Net AJAX框架使用前面的机制模拟了私有变量和函数,这种写法和C#很相像,十分的优雅。但是,处于效率的缘故,微软后来把它改成了这种原型的定义方式。虽然这种方式不那么优雅,但是很有效率。

 

在JavaScript中,这种封装的优雅和执行的效率之间的矛盾一直存在。现在我们最好的解决方案就是把数据定义在类里面,函数定义在类的prototype属性里面。

分享到:
评论
43 楼 sankooc 2010-01-05  
小问一下js里等号比较的是什么 值 还是?
42 楼 jessige_27 2010-01-04  
zzhonghe 写道
jessige_27 写道


但是 差别是有的 运行这个试试
var p1 = new Person();
var show = p1.show;
var p2 = new Person();
alert(show == p2.show); // false




楼上有没有跑一下啊, 这个怎么执行都是true.

关于优雅的问题,实在是没有规定说写成POJO那样就算优雅,关键还是在于习惯。prototype的方式,既好理解,又能方便重用,更易于扩展,是在没理由说它不优雅。


当然跑过 我发的帖子是针对楼主所说的
引用
实际上这种写法和上面一种没有什么不同:唯一的区别就是代码位置不同。这只是一个“看上去很甜”的语法糖,并没有实质性差别。

上面的那段代码 我没把所有的代码都帖上来
你是用正常的prototype方式定义的Person吧 那正好说明了楼主这种的方式有问题
运行下面的试试 这个就是false了
function Person() {
  Person.prototype.show = function() {
    alert("I'm a person.");
  }
}

var p1 = new Person();
var p1_show = p1.show;

var p2 = new Person();
alert(p1_show == p2.show); // false

alert(p1.show == p2.show); // true
41 楼 冯冀川 2009-11-04  
我觉得讨论这些问题的初衷,还是由于现在大量的js程序员是由java,php,c#程序员转过来的,或者说是有服务器端语言为基础,然后向前端衍生,前后台的代码都写,所以希望js能够模拟出某种语言的特性出来。
如果一个从最初就是从事于js代码编写的程序员,我想对该采取那种方式也就不会太在意了,因为js有他自己的方式
40 楼 zzhonghe 2009-11-01  
jessige_27 写道


但是 差别是有的 运行这个试试
var p1 = new Person();
var show = p1.show;
var p2 = new Person();
alert(show == p2.show); // false




楼上有没有跑一下啊, 这个怎么执行都是true.

关于优雅的问题,实在是没有规定说写成POJO那样就算优雅,关键还是在于习惯。prototype的方式,既好理解,又能方便重用,更易于扩展,是在没理由说它不优雅。
39 楼 jessige_27 2009-10-31  
引用
实际上这种写法和上面一种没有什么不同:唯一的区别就是代码位置不同。这只是一个“看上去很甜”的语法糖,并没有实质性差别。

这是错的
var p1 = new Person();
var p2 = new Person();
alert(p1.show == p2.show); // true

这么写确实得到的是true

但是 差别是有的 运行这个试试
var p1 = new Person();
var show = p1.show;
var p2 = new Person();
alert(show == p2.show); // false

注意别改变第二三行的顺序

原因是在new p2的时候 把prototype的show换掉了
而p1.show和p2.show实际上都是prototype.show 相等是当然的

引用
“看上去很甜”的语法糖
那里面不知道是什么东西
38 楼 vieri122 2009-09-17  
继续期待楼主的好文章
37 楼 shewa5337 2009-08-14  
看完了,应该说是扫了一遍,回去啃js设计模式,看起来挺好的一本书。
36 楼 roadray 2009-07-15  
jamiesun 写道
java中的getXXX,setXXX都令人快吐了,js还要搞这一套?


var person = new Object()
person.name = 'xxxx'
person.sex = 'y'

.............


我只喜欢这么搞。


我那个代码意在表示类属性写在function里,而方法写在prototype里,怪我例子写的不明显导致感觉是在模拟pojo
35 楼 jeff312 2009-07-14  
不过有点不太理解LZ的意思,prototype怎么就“不优雅”了呢?男人跟女人不一样,所以嘴上会多一小撮胡子;女人跟男人不一样,所以胸前会多两块肥肉……可是男人女人都很优雅啊。
34 楼 night_stalker 2009-07-14  
架构的作用就是把庞大的代码划分成相对独立的小块,小块只要满足要求,里面随便怎么搞都没问题。(不过我觉得数 M 的 javascript 就够扯蛋的了)

维护问题是 java 固有的,java 程序很啰嗦,导致很难维护,所以程序员都神经兮兮,无论写什么都在想维护的事情 ……
33 楼 jeff312 2009-07-14  
robinqu 写道
JavaScript权威指南 有写过模拟Class继承的例子,静态变量、局部变量、公有变量等等都可以模拟~
当时我读完了那一章就觉得累,何必去模拟自己无法做到的东西

所以用prototype继承才是Js的王道吧~要不然就有点东施效颦的感觉了~

说句非常不负责任的话,如果不是做稍微大一点的项目,也就50行左右的代码,你还管这么多么?肯定是非常面向过程的代码吧……汗
再大一点的东西,肯定会基于类库,jQuery之类……


类库是帮你少写点效果实现,它不能帮你解决商业逻辑问题,现在有不少系统(包括某些银行系统)都用javascript写整个前端,数M甚至数十M的代码量,这能靠类库堆积起来?不用面向对象设计,将来维护起来够你受的。
32 楼 jeff312 2009-07-13  
incredible 写道
本来就是不面向对象的东西


这你就错了,js全身上下都是对象,函数本身也是对象。之所以没法按照Java那样写闭包,仅仅是因为它是逐行解释的脚本语言,没法像静态编译语言那样重用字节码。
31 楼 墓里活人 2009-07-13  
jamiesun 写道
java中的getXXX,setXXX都令人快吐了,js还要搞这一套?


var person = new Object()
person.name = 'xxxx'
person.sex = 'y'

.............


我只喜欢这么搞。



还是太啰嗦了,要这么搞:
  
   var person = {};
   obj.name = "xxx";
   obj.sex = "yyy";
   obj.myFunction = function(){ alter(obj.name);  }

   var ePer = {};
   ePer ['field'] = 'field';
   ePer.myFunction  = function(){ alter(ePer .'field')  };
    //继承 - (重载)
   ePer.extendBy = function(parant){
          for(var i in person ){
            if(parant[i]=="undefine")continue;
            extendPer[i] =  parant[i];
         }
   }
   //进行继承 或重载。呵呵
   ePer.extendBy(person);
   
  
30 楼 jamiesun 2009-07-13  
java中的getXXX,setXXX都令人快吐了,js还要搞这一套?


var person = new Object()
person.name = 'xxxx'
person.sex = 'y'

.............


我只喜欢这么搞。

29 楼 robinqu 2009-07-13  
JavaScript权威指南 有写过模拟Class继承的例子,静态变量、局部变量、公有变量等等都可以模拟~
当时我读完了那一章就觉得累,何必去模拟自己无法做到的东西

所以用prototype继承才是Js的王道吧~要不然就有点东施效颦的感觉了~

说句非常不负责任的话,如果不是做稍微大一点的项目,也就50行左右的代码,你还管这么多么?肯定是非常面向过程的代码吧……汗
再大一点的东西,肯定会基于类库,jQuery之类……
28 楼 roadray 2009-07-12  
ranLoD 写道
roadray 写道
有没有人用这种?够不够优雅
var Person = function(){
   this.name = null;
   this.sex = null;
}

Person.prototype = {
  getName:function(){
    return this.name;
  },
  
  getSex:function(){
    return this.sex;
  }



}


这么烂的你也好意思贴出来,都被js书用烂了的例子

神仙你从哪飞来,吃了火药了,一上来就喷人,你NB,自己写个模式出来看看
这模式在YUI中大量应用,你的意思是YUI的代码页烂了哦
27 楼 black.angel 2009-07-08  
js 这东西,如果写成公用的API的确用类式继承比原型继承容易阅读和理解,不过效率就会慢很多。。。。。
26 楼 kjj 2009-07-03  
强扭的瓜不甜,本来没有oo特性的东西,真不知道价值在那里!
25 楼 pipilu 2009-07-03  
zhbh27 写道
我看了一书中有写到:“闭包”这种间接保持变量值的机制,往往会给JavaSript的垃圾回收器制造难题。特别是遇到对象间复杂的循环引用时,垃圾回收的判断逻辑非常复杂。无独有偶,IE浏览器早期版本确实存在JavaSript垃圾回收方面的内存泄漏问题。再加上“闭包”模型在性能测试方面的表现不佳,微软最终放弃了“闭包”模型,而改用“原型”模型,即prototype。


希望有人能证实一下这种说法的可靠性。
如果写javascript不用闭包我都不知道该怎么写。
24 楼 wkbulletin 2009-07-03  
脚步语言就自己的规则,为什么要把面向对象的规则强加给他呢

相关推荐

    JavaScript程序设计课件:面向对象概述.pptx

    JavaScript程序设计 面向过程与面向对象 6.1.1 面向过程与面向对象 1、概念 面向过程(Procedure Oriented)也可称之为“面向记录”,是一种以过程为中心的编程思想。它注重的是具体的步骤,只有按照步骤一步一步...

    基于JavaScript的面向对象程序设计研究.pdf

    基于JavaScript的面向对象程序设计研究 本文对基于JavaScript的面向对象程序设计进行了深入研究。研究发现,JavaScript语言具有良好的面向对象特性,特别是在封装性、继承性和多态性等方面。本文对JavaScript的面向...

    JavaScript面向对象编程指南(第2版).rar

    JavaScript是一种广泛...通过深入学习这本《JavaScript面向对象编程指南(第2版)》,开发者不仅能掌握JavaScript的面向对象编程基础,还能了解到实际项目中如何有效地运用这些知识,提升编程技巧和解决问题的能力。

    javascript 面向对象程序设计博客文章

    面向对象程序设计(Object-Oriented Programming,简称OOP)是软件工程中的一个重要概念,它通过类和对象来组织代码,实现数据封装、继承和多态等核心特性。在JavaScript中,虽然没有传统的类,但它提供了基于原型的...

    面向对象JavaScript开发

    JavaScript,作为一种广泛应用...JavaScript 面向对象程序设计——继承与多态.pdf 和 JavaScript 面向对象程序设计——封装.pdf 这两个文档可能深入探讨了这些主题,帮助读者深入理解并掌握JavaScript的面向对象开发。

    javascript 经典面向对象设计

    标题“JavaScript经典面向对象设计”指出了本书的主要内容是关于如何使用面向对象编程(OOP)原则和技术来编写高质量、可扩展且可重用的JavaScript应用程序及库。描述中提到本书相比其他中文资料更为清晰,深入到...

    javascript面向对象编程(中文).pdf

    ### JavaScript面向对象编程知识点概述 #### 一、现代JavaScript编程概览 - **JavaScript的演进**:自诞生以来,JavaScript经历了从一个简单的脚本语言到现今被广泛应用于构建复杂应用的强大编程语言的过程。它的...

    JavaScript面向对象程序程序设计PPT与代码

    JavaScript是一种广泛应用于Web开发的脚本语言,尤其在构建交互式网页和...这份"JavaScript面向对象程序程序设计PPT与代码"资源将详细解释这些概念,并可能包含实际示例,帮助你深入理解和应用这些面向对象编程技术。

    论述面向对象程序设计的必然性以及未来形势

    ### 论述面向对象程序设计的必然性以及未来形势 #### 面向对象程序设计的必然性 面向对象程序设计(Object-Oriented Programming,简称OOP)是一种编程范式,它通过将数据和处理数据的方法绑定在一起,形成一个...

    java 面向对象程序设计课件

    在"java 面向对象程序设计课件"中,我们可以深入探讨以下几个关键知识点: 1. **面向对象编程基础**:Java是面向对象的语言,其核心概念包括封装、继承和多态。封装允许我们将数据和操作数据的方法捆绑在一起,形成...

    javascript面向对象

    ### JavaScript面向对象编程详解 #### 引言 在软件工程领域,面向对象编程(OOP)是一种编程范式,它使用“对象”来设计软件。每个对象都可以包含数据(属性)和方法(行为)。JavaScript虽然起初并非为面向对象...

    javascript面向对象编程.pdf

    总而言之,学习现代JavaScript面向对象编程,有助于开发者在认识这门语言演化的基础上,运用面向对象的设计和编程模式来构建更加健壮和可维护的JavaScript应用程序。同时,测试和调试是保证代码质量不可或缺的环节,...

    javascript面向对象编程

    JavaScript是一种广泛应用于Web开发的动态、弱类型、基于原型的脚本语言,它不仅支持函数式编程,还具有强大的面向对象编程能力...通过阅读《javascript面向对象编程.pdf》这样的资料,你可以深入理解并掌握这些概念。

    JavaScript面向对象的程序设计(犯迷糊的小羊)

    面向对象程序设计的基本原则包括封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism),这被称为面向对象的三大特性。封装是隐藏对象内部状态和行为的过程,只暴露出操作接口。继承是子对象继承父对象...

    JavaScript面向对象编程指南 pdf

    下面将详细探讨JavaScript面向对象编程的基本原理、特性以及实际应用。 1. **类与对象** - 在JavaScript中,对象是键值对的集合,可以通过字面量语法或构造函数创建。例如: ```javascript const person = { ...

    Javascript 高级程序设计(第3版)超清中文PDF

    《JavaScript高级程序设计》(第3版)是一本深入探讨该语言精髓的权威书籍,它为读者提供了全面且深入的JavaScript知识,包括语言核心、DOM操作、BOM处理、事件处理以及面向对象编程等多个方面。 在书中,作者详细...

    JavaScript面向对象精要(英文版)

    ### JavaScript面向对象精要 #### 一、概述 《JavaScript面向对象精要》是一本深入讲解JavaScript面向对象编程原理的专业书籍。本书由知名的前端开发者Nicholas C. Zakas撰写,全面介绍了JavaScript作为一种动态...

    javascript面向对象框架

    "javascript面向对象框架"这一主题涵盖了JavaScript中实现面向对象编程的框架,特别是Prototype和MooTools这两个优秀的库。 Prototype是JavaScript的一个开源库,它扩展了JavaScript的基本对象和函数,提供了强大的...

Global site tag (gtag.js) - Google Analytics