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属性里面。

出处: http://devbean.blog.51cto.com/448512/174940

时间: 2024-12-31 04:36:45

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

JavaScript面向对象程序设计教程_javascript技巧

JavaScript中对象的定义为:无序属性的集合,其属性可以包含基本值.对象或者函数.可以把对象想象成散列表,就是一组名值对(key:value),其中值可以是数据或函数,每个对象都是基于一个引用类型创建的. 理解对象 前面的博客里写过创建对象的方式有两种,一种是创建一个object的实例,另一种是使用对象字面量法: var person = new Object(); person.sex = man; person.name = bluce person.age = 58; person.

javascript面向对象程序设计高级特性经典教程(值得收藏)_javascript技巧

本文实例讲述了javascript面向对象程序设计的高级特性.分享给大家供大家参考,具体如下: 1.创建对象的三种方式: 第一种构造法:new  Object var a = new Object(); a.x = 1, a.y = 2; 第二种构造法:对象直接量 var b = { x : 1, y : 2 }; 第三种构造法:定义类型 function Point(x, y){ this.x = x; this.y = y; } var p = new Point(1,2); 2.访问对象

Javascript 面向对象编程(一)封装

学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难.因为Javascript的Object模型很独特,和其他语言都不一样,初学者不容易掌握. 下面就是我的学习笔记,希望对大家学习这个部分有所帮助.我主要参考了以下两本书籍: <面向对象的Javascript>(Object-Oriented JavaScript) <Javascript高级程序设计(第二版)>(Professional JavaScript for Web Developers, 2nd

JavaScript面向对象程序设计(1) 前言

基于对象还是面向对象? 面向对象技术是现代软件开发中的重要技术之一.面向对象变成的好处毋庸置疑,现在的主流语言如 Java.C++都是面向对象的.现在的面向对象理论更多的是使用Java或C++进行描述,究其根源,在于这 些语言都是传统的面向对象语言,具有面向对象理论所指明的一切特性:类.封装.继承.多态等等. 相比而言,一些动态语言如JavaSript就显得不那么面向对象--至少,在JavaScript中 并没有类class这一关键字.但是,在JavaScript中并不是没有类的概念.于是有人说

Javascript 面向对象编程(一) 封装_js面向对象

学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难.因为Javascript的Object模型很独特,和其他语言都不一样,初学者不容易掌握. 下面就是我的学习笔记,希望对大家学习这个部分有所帮助.我主要参考了以下两本书籍: <面向对象的Javascript>(Object-Oriented JavaScript) <Javascript高级程序设计(第二版)>(Professional JavaScript for Web Developers, 2nd

JavaScript面向对象程序设计(5) 类

类是面向对象程序设计的核心概念之一.一个类代表了具有相似属性的一类事物的抽象.从本篇开始 ,我们将正式的进入JavaScript的面向对象部分.首先需要注意的是,在JavaScript中并没有"类 "这一关键字--在大多数语言中都是使用class作为关键字的.所以,这里的类就成 了一个概念,它没有明确的语法标志. 1.类和构造函数 前面说过,在JavaScript中并没有明确的类的概念.实际上,我们给出的只是类的构造函数.类的构 造函数构成了这个类的全部内容.既然叫做构造函数,它也是一

JavaScript面向对象程序设计(3) 对象

1.对象 对象是面向对象程序设计的基础概念之一,只需看看这个名字就已经知道了.在我们 熟悉的面向对象语言中,比如Java或者C++,都有着类似的对象定义方法.比如,我们想定义一个类,名 字叫Person,有两个属性:name和age,另外有一个方法,将显示出这个Person对象的名字和年龄,那么 我们可以用下面的代码实现: Java: public class Person { private String name; private int age; public String getName

JavaScript面向对象程序设计(6) 封装

封装是面向对象的重要概念之一.如果一个程序没有封装性,也就谈不上什么面向对象.但是, JavaScript并不像其他的语言,比如 Java,有公有变量和私有变量等:在JavaScript中只有一种作用域 :公有作用域.在本章中,我们将会见识到JavaScript是如何实现封装的特性的. 1.this和公 有变量 首先需要理解this关键字.看下面的一段代码,你应该对此感到熟悉: function Person(name, age) { this.name = name; // 定义一个公有变量

JavaScript面向对象程序设计(2) 数组

或许你会奇怪,面向对象的程序设计为什么从数组开始讲起?这是因为--其间的种种 关系吧--嘿嘿,这里先卖个关子,先来看看我们熟悉的数组在JavaScript里面是什么样 子的. 1.创建数组 在JavaScript中有很多创建数组的方法.比如使用Array函数.不过 这不是现在我们要讲述的.现在我们使用简单的方括号"[]"的办法来创建数组. var objAyyar = []; // 1 var objAyyar = [2]; // 2 var objAyyar = ["a&q