JavaScript内核系列 第8章 面向对象的JavaScript(上)第八章 面向对象的Javascript面向对象编程思想在提出
JavaScript内核系列 第8章 面向对象的JavaScript(上)
第八章 面向对象的Javascript
面向对象编程思想在提出之后,很快就流行起来了,它将开发人员从冗长,繁复,难以调试的过程式程序中解放了出来,过程式语言如C,代码的形式往往如此:
Component comp;init_component(& comp, props);
?
Component comp;comp.init(props);
?
JavaScript中的继承可以通过原型链来实现,调用对象上的一个方法,由于方法在JavaScript对象中是对另一个函数对象的引用,因此解释器会在对象中查找该属性,如果没有找到,则在其内部对象prototype对象上搜索,由于prototype对象与对象本身的结构是一样的,因此这个过程会一直回溯到发现该属性,则调用该属性,否则,报告一个错误。关于原型继承,我们不妨看一个小例子:
?
?
function Base(){ this .baseFunc = function (){ print ( "base behavior" ); }} function Middle(){ this .middleFunc = function (){ print ( "middle behavior" ); }} Middle. prototype = new Base(); function Final(){ this .finalFunc = function (){ print ( "final behavior" ); }}Final. prototype = new Middle(); function test(){ var obj = new Final(); obj.baseFunc(); obj.middleFunc(); obj.finalFunc();}
?

?
图 原型链的示意图
?
在function test中,我们new了一个Final对象,然后依次调用obj.baseFunc,由于obj对象上并无此方法,则按照上边提到的规则,进行回溯,在其原型链上搜索,由于Final的原型链上包含Middle,而Middle上又包含Base,因此会执行这个方法,这样就实现了类的继承。
?
但是这种继承形式与传统的OO语言大相径庭,初学者很难适应,我们后边的章节会涉及到一个比较好的JavaScript的面向对象基础包Base,使用Base包,虽然编码风格上会和传统的OO语言不同,但是读者很快就会发现这种风格的好处。8.1.1引用
引用是一个比较有意思的主题,跟其他的语言不同的是,JavaScript中的引用始终指向最终的对象,而并非引用本身,我们来看一个例子:
?
?
var obj = {}; // 空对象var ref = obj; // 引用 obj. name = "objectA" ;print ( ref . name ); //ref 跟着添加了 name 属性 obj = [ "one" , "two" , "three" ]; //obj 指向了另一个对象 ( 数组对象 )print ( ref . name ); //ref 还指向原来的对象print (obj. length ); //3print ( ref . length ); //undefined
obj只是对一个匿名对象的引用,所以,ref并非指向它,当obj指向另一个数组对象时
?
var obj = {}; // 新建一个对象,并被 obj 引用 var ref1 = obj; //ref1 引用 obj, 事实上是引用 obj 引用的空对象var ref2 = obj; obj.func = "function" ; print (ref1.func);print (ref2.func);
?
根据运行结果我们可以看出,在定义了引用之后,修改原始的那个对象会影响到其引用上,这一点也应该注意。
8.1.2 new操作符
有面向对象编程的基础有时会成为一种负担,比如看到new的时候,Java程序员可能会认为这将会调用一个类的构造器构造一个新的对象出来,我们来看一个例子:
?
function Shape(type){ this .type = type || "rect" ; this .calc = function (){ return "calc, " + this .type; }} var triangle = new Shape( "triangle" );print (triangle.calc()); var circle = new Shape( "circle" );print (circle.calc());
?
?
?
var triangle = new Shape( "triangle" );// 上一句相当于下面的代码var triangle = {};Shape.apply(triangle, [ "triangle" ]);
?
8.2封装
事实上,我们可以通过JavaScript的函数实现封装,封装的好处在于未经授权的客户代码无法访问到我们不公开的数据,我们来看这个例子:
?
?
function Person(name){ //private variable var address = "The Earth" ; //public method this .getAddress = function (){ return address; } //public variable this .name = name;} //publicPerson.prototype.getName = function (){ return this .name;} //publicPerson.prototype.setName = function (name){ this .name = name;}
var jack = new Person( "jack" );print(jack.name);//jackprint(jack.getName());//jackprint(jack.address);//undefinedprint(jack.getAddress());//The Earth
function Person(name){ //private variable var address = "The Earth" ; //public method this .getAddress = function (){ return address; } //public variable this .name = name;} Person.TAG = "javascript-core" ;// 静态变量 print(Person.TAG);
?
?
Base是由Dean Edwards开发的一个JavaScript的面向对象的基础包,Base本身很小,只有140行,但是这个很小的包对面向对象编程风格有很好的支持,支持类的定义,封装,继承,子类调用父类的方法等,代码的质量也很高,而且很多项目都在使用Base作为底层的支持。尽管如此,JavaScript的面向对象风格依然非常古怪,并不可以完全和传统的OO语言对等起来。
下面我们来看几个基于Base的例子,假设我们现在在开发一个任务系统,我们需要抽象出一个类来表示任务,对应的,每个任务都可能会有一个监听器,当任务执行之后,需要通知监听器。我们首先定义一个事件监听器的类,然后定义一个任务类:
var EventListener = Base.extend({ constructor : function(sense){ this.sense = sense; }, sense : null, handle : function(){ print(this.sense+" occured"); }}); var Task = Base.extend({ constructor : function(name){ this.name = name; }, name : null, listener : null, execute : function(){ print(this.name); this.listener.handle(); }, setListener : function(listener){ this.listener = listener; }});
var printing = new Task("printing");var printEventListener = new EventListener("printing");printing.setListener(printEventListener);printing.execute();
var HttpRequester = Task.extend({ constructor : function(name, host, port){ this.base(name); this.host = host; this.port = port; }, host : "127.0.0.1", port : 9527, execute : function(){ print("["+this.name+"] request send to "+this.host+" of port "+this.port); this.listener.handle(); }});
var requester = new HttpRequester("requester1", "127.0.0.1", 8752);var listener = new EventListener("http_request");requester.setListener(listener);requester.execute();
this.base(name);
?
?
在很多应用中,有些对象不会每次都创建新的实例,而是使用一个固有的实例,比如提供数据源的服务,报表渲染引擎,事件分发器等,每次都实例化一个会有很大的开销,因此人们设计出了单例模式,整个应用的生命周期中,始终只有顶多一个实例存在。Base同样可以模拟出这样的能力:
?
var ReportEngine = Base.extend({ constructor : null, run : function(){ //render the report } });
?
var HttpRequester = Task.extend({ constructor : function(name, host, port){ this.base(name); this.host = host; this.port = port; }, host : "127.0.0.1", port : 9527, execute : function(){ print("["+this.name+"] request send to "+this.host+" of port "+this.port); this.listener.handle(); }});
是从实际项目中提取出来的,还是只是个例子?var HttpRequester = Task.extend({ constructor : function(name, host, port){ this.base(name); this.host = host; this.port = port; }, host : "127.0.0.1", port : 9527, execute : function(){ print("["+this.name+"] request send to "+this.host+" of port "+this.port); this.listener.handle(); }});
是从实际项目中提取出来的,还是只是个例子?
呵呵,这个目前还只是一个例子,不能用于发送Http请求,但是如果结合宿主语言的话,应该是可以实现的。我现在也正在研究怎么把JavaScript变得更有用,特别是在其他环境下,而不仅仅局限在客户端。function Shape(type){ this .type = type || "rect" ; this .calc = function (){ return "calc, " + this .type; }}
如果执行环境是客户端,那么此代码只是为window对象添加了一个名为Shape的属性,这个属性的值是一个对象,这个过程中没有类的概念。
而代码:
var triangle = new Shape( "triangle" );print (triangle.calc());
不过是对函数使用new操作符:
function Shape(type){ this .type = type || "rect" ; this .calc = function (){ return "calc, " + this .type; }}
如果执行环境是客户端,那么此代码只是为window对象添加了一个名为Shape的属性,这个属性的值是一个
对象,这个过程中没有类的概念。
这个没问题,从传统oo语言角度看,JS 是没有类的
我困惑的是,这本书的受众定位。从开头举的 C 和 Java 的例子,感觉这一章是写给有传统oo语言背景的读者看的。从这个出发点去写,提到了类,又说 JS 没有类,强调机制不同,但文中并没有深入解释,感觉这样读者更困惑。对于无传统oo语言背景的读者来说,则感觉有点蜻蜓点水,没说到点子上,感觉很不过瘾。
类的定义,我觉得也不必局限于传统oo的解释。类是什么?物以类聚,类的本意是同类,是共性。class 是种类,是分类。类在计算机语言里,是对自然界万事万物,按照属性和行为所进行的抽象。从这个角度讲,JS 里的 function, 已经能表达类的原生含义,为什么不能称呼为类呢?
传统oo语言里的 Class 是类,JS语言里的 function 也是类,只是实现机制不同。
var triangle = new Shape( "triangle" );print (triangle.calc());
不过是对函数使用new操作符:
言如</span>
<span lang="EN-US">C</span>
<span>,代码的形式往往如此:</span>
</p>
<p style="text-align: left;" align="left"><span style="font-size: small;"><span style="font-size: 13px;"><br></span></span></p>
<p><span style="font-size: small;">
</span>
</p>
<pre name="code" style="text-indent: 21.0pt;"><span lang="EN-US">JavaScript</span>
<span>中的继承可以通过原型链来实现,调用对象上的一个方法,由于方法在</span>
<span lang="EN-US">JavaScript</span>
<span>对象中是对另一个函数对象的引用,因此解释器会在对象中查找该属性,如果没有找到,则在其内部对象</span>
<span lang="EN-US">prototype</span>
<span>对象上搜索,由于</span>
<span lang="EN-US">prototype</span>
<span>对象与对象本身的结构是一样的,因此这个过程会一直回溯到发现该属性,则调用该属性,否则,报告一个错误。关于原型继承,我们不妨看一个小例
子:</span>
</p>
<p style="text-indent: 21.0pt;"><span lang="EN-US">?</span>
</p>
<p style="text-align: left;" align="left">?</p>
<p><span style="font-size: small;"><strong>
</strong>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" );
}
}
function Middle(){
this .middleFunc = function (){
print ( "middle behavior" );
}
}
Middle. prototype = new Base();
function Final(){
this .finalFunc = function (){
print ( "final behavior" );
}
}
Final. prototype = new Middle();
function test(){
var obj = new Final();
obj.baseFunc();
obj.middleFunc();
obj.finalFunc();
}</pre>
</strong></p>
<p><strong><br></strong></p>
<p>?</p>
<table style="height: 664px;" border="0" width="186"><tbody><tr>
<td>
<br><img src="http://dl.iteye.com/upload/attachment/244943/271d988b-ae09-31bb-a63f-7b6fc1261c31.png" alt="JavaScript内核系列 第8章 面向对象的JavaScript(下)" width="206" height="479"><br>
?</td>
</tr></tbody></table>
<p style="text-indent: 21.0pt;"><span>图</span>
<span style="font-size: 10.0pt;"> </span>
<span>原型链的示意图</span>
</p>
<p style="text-indent: 21.0pt;"><span style="font-size: 10.0pt;" lang="EN-US">?</span>
</p>
<p style="text-indent: 21.0pt;"><span>在</span>
<span style="font-size: 10.0pt;" lang="EN-US">function test</span>
<span>中,我们</span>
<span style="font-size: 10.0pt;" lang="EN-US">new</span>
<span>了一个</span>
<span style="font-size: 10.0pt;" lang="EN-US">Final</span>
<span>对象,然后依次调用</span>
<span style="font-size: 10.0pt;" lang="EN-US">obj.baseFunc</span>
<span>,由于</span>
<span style="font-size: 10.0pt;" lang="EN-US">obj</span>
<span>对象上并无此方法,则按照上边提到的规则,进行回溯,在其原型链上搜索,由于</span>
<span style="font-size: 10.0pt;" lang="EN-US">Final</span>
<span>的原型链上包含</span>
<span style="font-size: 10.0pt;" lang="EN-US">Middle</span>
<span>,而</span>
<span style="font-size: 10.0pt;" lang="EN-US">Middle</span>
<span>上又包含</span>
<span style="font-size: 10.0pt;" lang="EN-US">Base</span>
<span>,因此会执行这个方法,这样就实现了类的继承。</span>
</p>
<p style="text-align: left;" align="left">?</p>
<p><span style="font-size: small;">
</span>
</p>
<div style="text-indent: 21.0pt;"><span>但是这种继承形式与传统的</span>
<span lang="EN-US">OO</span>
<span>语言大相径庭,初学者很难适应,我们后边的章节会涉及到一个比较好的</span>
<span lang="EN-US">JavaScript</span>
<span>的面向对象基础包</span>
<span lang="EN-US">Base</span>
<span>,使用</span>
<span lang="EN-US">Base</span>
<span>包,虽然编码风格上会和传统的</span>
<span lang="EN-US">OO</span>
<span>语言不同,但是读者很快就会发现这种风格的好处。</span>
</p>
<h4>
<a name="_Toc260749011"><span lang="EN-US">8.1.1</span>
</a>
<span><span>引用</span>
</span>
</h4>
<p style="text-indent: 21.0pt;"><span>引用是一个比较有意思的主题,跟其他的语言不同的是,</span>
<span lang="EN-US">JavaScript</span>
<span>中的引用始终指向最终的对象,而并非引用本身,我们来看一个例子:</span>
</p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US">?</span>
</strong>
</p>
<p style="text-align: left;" align="left">?</p>
<p><span style="font-size: small;"><strong>
</strong>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" ;
print ( ref . name ); //ref 跟着添加了 name 属性
obj = [ "one" , "two" , "three" ]; //obj 指向了另一个对象 ( 数组对象 )
print ( ref . name ); //ref 还指向原来的对象
print (obj. length ); //3
print ( ref . length ); //undefined</pre>
</strong></p>
<p><strong><br></strong></p>
<p style="text-indent: 21.0pt;"><span lang="EN-US">obj</span>
<span>只是对一个匿名对象的引用,所以,</span>
<span lang="EN-US">ref</span>
<span>并非指向它,当</span>
<span lang="EN-US">obj</span>
<span>指向另一个数组对象时</span>
</p>
<p style="text-align: left;" align="left">?</p>
<p><span style="font-size: small;"><strong>
</strong>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" ;
print (ref1.func);
print (ref2.func);</pre>
</strong></p>
<p><strong><br></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: small;"><span style="font-size: 13px;"><strong><br></strong>
</span>
</span>
</p>
<p style="text-align: left;" align="left">?</p>
<p><span style="font-size: small;"><strong>
</strong>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<div style="text-indent: 21.0pt;"><span>根据运行结果我们可以看出,在定义了引用之后,修改原始的那个对象会影响到其引用上,这一点也应该注意。</span>
</p>
<h4>
<a name="_Toc260749012"><span lang="EN-US">8.1.2
new</span>
</a>
<span><span>操作符</span>
</span>
</h4>
<p style="text-indent: 21.0pt;"><span>有面向对象编程的基础有时会成为一种负担,比如看到</span>
<span lang="EN-US">new</span>
<span>的时候,</span>
<span lang="EN-US">Java</span>
<span>程序员可能会认为这将会调用一个类的构造器构造一个新的对象出来,我们来看一个例子:</span>
</p>
<p style="text-align: left;" align="left">?</p>
<p><span style="font-size: small;"><strong>
</strong>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" ;
this .calc = function (){
return "calc, " + this .type;
}
}
var triangle = new Shape( "triangle" );
print (triangle.calc());
var circle = new Shape( "circle" );
print (circle.calc());</pre>
</strong></p>
<p>?</p>
<p>?</p>
<p lang="EN-US">Java</span>
<span>程序员可能会觉得</span>
<span style="font-size: 10.0pt;" lang="EN-US">Shape</span>
<span>就是一个类,然后</span>
<span style="font-size: 10.0pt;" lang="EN-US">triangle</span>
<span>,</span>
<span style="font-size: 10.0pt;" lang="EN-US">circle</span>
<span>即是</span>
<span style="font-size: 10.0pt;" lang="EN-US">Shape</span>
<span>对应的具体对象,而其实</span>
<span style="font-size: 10.0pt;" lang="EN-US">JavaScript</span>
<span>并非如此工作的,罪魁祸首即为此</span>
<span style="font-size: 10.0pt;" lang="EN-US">new</span>
<span>操作符。在</span>
<span style="font-size: 10.0pt;" lang="EN-US">JavaScript</span>
<span>中,通过</span>
<span style="font-size: 10.0pt;" lang="EN-US">new</span>
<span>操作符来作用与一个函数,实质上会发生这样的动作:</span>
</p>
<p lang="EN-US">apply</span>
<span>方法,将这个空对象传入作为</span>
<span style="font-size: 10.0pt;" lang="EN-US">apply</span>
<span>的第一个参数,及上下文参数。这样函数内部的</span>
<span style="font-size: 10.0pt;" lang="EN-US">this</span>
<span>将会被这个空的对象所替代:</span>
</p>
<p lang="EN-US">?</span>
</p>
<p style="text-align: left;" align="left">?</p>
<p><span style="font-size: small;"><strong>
</strong>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" );
// 上一句相当于下面的代码
var triangle = {};
Shape.apply(triangle, [ "triangle" ]);</pre>
</strong></p>
<p>?</p>
<h3>
<a name="_Toc260749013"><span lang="EN-US">8.2</span>
</a>
<span><span>封装</span>
</span>
</h3>
<p style="text-indent: 21.0pt;"><span>事实上,我们可以通过</span>
<span lang="EN-US">JavaScript</span>
<span>的函数实现封装,封装的好处在于未经授权的客户代码无法访问到我们不公开的数据,我们来看这个例子:</span>
</p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US">?</span>
</strong>
</p>
<p style="text-align: left;" align="left">?</p>
<p><span style="font-size: small;"><strong>
</strong>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" ;
//public method
this .getAddress = function (){
return address;
}
//public variable
this .name = name;
}
//public
Person.prototype.getName = function (){
return this .name;
}
//public
Person.prototype.setName = function (name){
this .name = name;
}</pre>
</strong></p>
<p><strong><br></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: small;"><span style="font-size: 13px;"><strong>
</strong>
</span>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" );
print(jack.name);//jack
print(jack.getName());//jack
print(jack.address);//undefined
print(jack.getAddress());//The Earth</pre>
</strong></p>
<p><strong><br></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: small;"><span style="font-size: 13px;"><strong>
</strong>
</span>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" ;
//public method
this .getAddress = function (){
return address;
}
//public variable
this .name = name;
}
Person.TAG = "javascript-core" ;// 静态变量
print(Person.TAG);</pre>
</strong></p>
<p>?</p>
<p>?</p>
<p style="text-indent: 21.0pt;"><span lang="EN-US">Base</span>
<span>是由</span>
<span lang="EN-US">Dean
Edwards</span>
<span>开发的一个</span>
<span lang="EN-US">JavaScript</span>
<span>的
面向对象的基础包,</span>
<span lang="EN-US">Base</span>
<span>本身很小,只有</span>
<span lang="EN-US">140</span>
<span>行,但是这个很小的包对面向对象编程风格有很好的支持,支持类的定义,封装,继承,子类调用
父类的方法等,代码的质量也很高,而且很多项目都在使用</span>
<span lang="EN-US">Base</span>
<span>作为底
层的支持。尽管如此,</span>
<span lang="EN-US">JavaScript</span>
<span>的面向对象风格依然非常古
怪,并不可以完全和传统的</span>
<span lang="EN-US">OO</span>
<span>语言对等起来。</span>
</p>
<p style="text-indent: 21.0pt;"><span>下面我们来看几个基于</span>
<span lang="EN-US">Base</span>
<span>的例子,
假设我们现在在开发一个任务系统,我们需要抽象出一个类来表示任务,对应的,每个任务都可能会有一个监听器,当任务执行之后,需要通知监听器。我们首先定
义一个事件监听器的类,然后定义一个任务类:</span>
</p>
<p style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong>
</span>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" occured");
}
});
var Task = Base.extend({
constructor : function(name){
this.name = name;
},
name : null,
listener : null,
execute : function(){
print(this.name);
this.listener.handle();
},
setListener : function(listener){
this.listener = listener;
}
});</pre>
</strong></p>
<p><strong><br></strong></p>
<p style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong>
</span>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; font-size: small;"><span style="font-size: 13px;">
</span>
</span>
</p>
<div style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong>
</span>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" of port "+this.port);
this.listener.handle();
}
});</pre>
</strong></p>
<p><strong><br></strong></p>
<p style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong>
</span>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; font-size: small;"><span style="font-size: 13px;">
</span>
</span>
</p>
<div style="text-indent: 21.0pt;"><span>在很多应用中,有些对象不会每次都创建新的实例,而是使用一个固有的实例,比如提供数据源的服务,报表渲染引擎,事件分发
器等,每次都实例化一个会有很大的开销,因此人们设计出了单例模式,整个应用的生命周期中,始终只有顶多一个实例存在。</span>
<span lang="EN-US">Base</span>
<span>同样可以模拟出这样的能力:</span>
</p>
<p style="text-indent: 21.0pt;"><span lang="EN-US">?</span>
</p>
<p style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong>
</span>
</span>
</p>
<p><strong>
</strong></p>
<p><strong>
<pre name="code" name="code">function Shape(type){ this .type = type || "rect" ; this .calc = function (){ return "calc, " + this .type; }}
如果执行环境是客户端,那么此代码只是为window对象添加了一个名为Shape的属性,这个属性的值是一个
对象,这个过程中没有类的概念。
这个没问题,从传统oo语言角度看,JS 是没有类的
我困惑的是,这本书的受众定位。从开头举的 C 和 Java 的例子,感觉这一章是写给有传统oo语言背景的读者看的。从这个出发点去写,提到了类,又说 JS 没有类,强调机制不同,但文中并没有深入解释,感觉这样读者更困惑。对于无传统oo语言背景的读者来说,则感觉有点蜻蜓点水,没说到点子上,感觉很不过瘾。
类的定义,我觉得也不必局限于传统oo的解释。类是什么?物以类聚,类的本意是同类,是共性。class 是种类,是分类。类在计算机语言里,是对自然界万事万物,按照属性和行为所进行的抽象。从这个角度讲,JS 里的 function, 已经能表达类的原生含义,为什么不能称呼为类呢?
传统oo语言里的 Class 是类,JS语言里的 function 也是类,只是实现机制不同。
var triangle = new Shape( "triangle" );print (triangle.calc());
不过是对函数使用new操作符:
嗯,你的意见很好,可能跟个人的经历有关,就假想读者写文章的人和我有同样的背景,呵呵。说到传统的OO和JavaScript的一些核心概念的区别,我更倾向于不要进行类比。可是,这一章我自己却列举了C/Java中的例子,诱惑读者进行类比,呵呵。
我会考虑你的建议,并完善这个系列,谢谢。
12 楼 ordinaryworld 2010-05-11 这个不是jquery之父写的精通JavaScript吗? 13 楼 abruzzi 2010-05-11 ordinaryworld 写道这个不是jquery之父写的精通JavaScript吗?
你看过精通JavaScript吗?其实你看没看过都无所谓,我不是jQuery之父。 14 楼 liushilang 2010-05-20 楼主abruzzi 没有把“引用”这个讲明白,能否再补充点内容 15 楼 abruzzi 2010-05-20 liushilang 写道楼主abruzzi 没有把“引用”这个讲明白,能否再补充点内容
不好意思,最近这段时间,刚刚在新公司入职,有很多东西要学习,暂时没有精力来写这个。等后边有时间了,在补充下,如果临时赶制,会影响文档的质量。