探讨JavaScript:优雅的封装还是执行效率?(1)
优雅封装的程序看起来是那么的美妙:每个属性被隐藏在对象之后,你所能看到的就是这个对象让你看到的,至于它到底是怎么操作的,这个不需要你操心。
执行的效率就是另外一回事。就像是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
- 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,每个对象的方法其实指向了同一份代码的拷贝,而不是每个对象都会有自己的代码拷贝。






