阿当的博客











{十月 29, 2008}   [转载 js]javascript的陷井

看到一不错的js问题汇总的贴,值得一读。

原文地址:http://dancewithnet.com/2008/10/27/javascript-gotchas/

==========================================

这本来是翻译Estelle Weyl的《15 JavaScript Gotchas》,里面介绍的都是在JavaScript编程实践中平时容易出错或需要注意的地方,并提供避开这些陷阱的方法,总体上讲,就是在认清事物本质的基础样要坚持好的编程习惯,其实这就是Douglas Crockford很久以前提出的JavaScript风格要素问题了,有些内容直接是相同的,具体请看《Javascript风格要素(1)》《Javascript风格要素(2)》。在翻译的过程中,我又看到了贤安去年翻译的《JavaScript的9个陷阱及评点》,其内容又有些交叉在一起,所以我就在现有翻译的基础上做了一个简单的拼合,并依据自己的理解增加了一些注释和解释。

  1. 区分大小写:变量名、属性和方法全部都区分大小写
  2. 不匹配的引号、圆括号或花括号将抛出错误
  3. 条件语句:3个常见陷阱
  4. 换行:一直用分号结束语句来避免常见的换行问题
  5. 标点法:在对象声明的尾部逗号将导致出错
  6. HTML id 冲突
  7. 变量作用域:全局变量对局部变量
  8. 函数重载:当重载不存在时,覆盖函数
  9. 区分string.replace()函数不是全局的
  10. parseInt应该包含两个参数
  11. “this”和绑定问题
  12. 为参数设置默认值,以免你遗漏它们
  13. for each循环是用于对象而不是数组
  14. switch语句需要点技巧
  15. 总是在检查undefined前检查null
  16. 时间处理陷阱

区分大小写

变量名和函数名都是区分大小写的。就像配错的引号一样,这些大家都知道。但是,由于错误是不作声的,所以这是一个提醒。为自己选择一个命名规则,并坚持它。而且,记住JavaScript中的原生函数和CSS属性都是骆驼拼写法(camelCase)

getElementById(’myId’) != getElementByID(’myId’); //它应该是“Id”而不是“ID”
getElementById(’myId‘) != getElementById(’myID‘); // “Id”也不等于“ID”

document.getElementById('myId').style.Color; //返回 "undefined"

不匹配的引号、圆括号或花括号

避免陷入不匹配的引号、圆括号或花括号陷阱的最好方式是编码时一直同时写出打开和关闭这两个元素符号,然后在其中间加入代码。开始:

var myString = ""; //在输入字符串值之前写入这对引号
function myFunction(){
 if(){//关闭每个打开的括弧
 }
}
//统计所有的左括号和右括号数量,并且确保它们相等
alert(parseInt(var1)*(parseInt(var2)+parseInt(var3))); //关闭每个打开的圆括号

每当你打开一个元素,请关闭它。当你添加了关闭圆括号后,你再把函数的参数放进圆括号中。如果有一串圆括号,统计所有打开的圆括号和所有关闭的圆括号,并且确保这两个数字相等。

条件语句(3个陷阱)

  1. 所有的条件语句都必须位于圆括号中。
    if(var1 == var2){}
  2. 不要犯无意地使用赋值运算符的错误:把第二个参数的值赋给第一个参数。因为它是一个逻辑问题,它将一直返回true且不会报错。
    if(var1 = var2){} // 返回true。把var2赋值给var1
  3. JavaScript是弱类型,除了在switch语句中。当JavaScript在case比较时,它是非弱类型。
    var myVar = 5;
    if(myVar == '5'){ //返回true,因为JavaScript是弱类型
     alert("hi");  //这个alert将执行,因为JavaScript通常不在意数据类型
    }
    switch(myVar){
     case '5':
     alert("hi"); //这个alert将不会执行,因为数据类型不匹配
    }
    

换行

当心JavaScript中的硬换行。换行被解释为表示行结束的分号。即使在字符串中,如果在引号中包括了一个硬换行,那么你会得到一个解析错误(未结束的字符串)。

var bad  = '<ul id="myId">
  <li>some text</li>
  <li>more text</li>
  </ul>'; // 未结束的字符串错误

var good = '<ul id="myId">' +
 ‘<li>some text</li>‘ +
 ‘<li>more text</li>‘ +
 ‘</ul>’; // 正确

前面讨论过的换行被解释为分号的规则并不适用于控制结构这种情况:条件语句关闭圆括号后的换行并不是给其一个分号。

一直使用分号和圆括号,那么你不会因换行而出错,你的代码易于阅读,且除了那些不使用分号的怪异源码外你会少一些顾虑:所以当移动代码且最终导致两个语句在一行时,你无需担心第一个语句是否正确结束。

多余的逗号

在任何JavaScript对象定义中,最后一个属性决不能以一个逗号结尾。Firefox不会出错,而IE会报语法错误。

var theObj = {
        city : "Boston",
        state : "MA",//IE6和IE7中有“缺少标识符、字符串或数字”的错误,IE8 beta2修正了它
  }

HTML id 冲突

JavaScript DOM绑定(JavaScript DOM bindings)允许通过HTML id索引。在JavaScript中函数和属性共享同一个名字空间。所以,当在HTML中的一个id和函数或属性有相同的名字时,你会得到难以跟踪的逻辑错误。然而这更多是一个CSS最佳实践的问题,当你不能解决你的JavaScript问题时,想起它是很重要的。


<ul>
<li id="length">1</li>
<li id="thisLength">2</li>
<li id="thatLength">3</li>
</ul>
<script>
var listitems = document.getElementsByTagName('li');
var liCount = listitems.length; //IE下返回的是<li id="length">1</li>这个节点而不是所有<li的数量

var thisLength = document.getElementById('thisLength');
    thatLength = document.getElementById('thatLength');
    //IE下会出现“对象不支持此属性和方法”的错误,IE8 beta2下首次加载页面会出错,刷新页面则不会
    //在IE中thisLength和thatLength直接表示以其为id值的DOM节点,
    //所以赋值时会出错,当有var声明时,IE会把其当着变量,这个时候就正常了。
</script>

如果你要标记(X)HTML,绝不要使用JavaScript方法或属性名作为id的值。并且,当你写JavaScript时,避免使用 (X)HTML中的id值作为变量名。

变量作用域

JavaScript中的许多问题都来自于变量作用域:要么认为局部变量是全局的,要么用函数中的局部变量覆盖了全局变量。为了避免这些问题,最佳方案是根本没有任何全局变量。但是,如果你有一堆,那么你应该知道这些陷阱。

不用var关键字声明的变量是全局的。记住使用var关键字声明变量,防止变量具有全局作用域。在下面例子中,在函数中声明的变量具有全局变量,因为没有使用var关键字声明:

anonymousFuntion1 = function(){
 globalvar = 'global scope'; //全局声明,因为“var”遗漏了
 return localvar;
}();
alert(globalvar); //弹出“global scope”,因为函数中的变量是全局声明

anonymousFuntion2 = function(){
 var localvar = 'local scope'; //使用“var”局部声明
 return localvar;
}();
alert(localvar); //错误 “localvar未定义”。没有全局定义localvar

作为参数引进到函数的变量名是局部的。如果参数名也是一个全局变量的名字,像参数变量一样有局部作用域,这没有冲突。如果你想在函数中改变一个全局变量,这个函数有一个参数复制于这个全局变量名,记住所有全局变脸都是window对象的属性。

var myscope = "global";
function showScope(myscope){
 return myscope; //局部作用域,即使有一个相同名字的全局变量
}
alert(showScope('local'));

function globalScope(myscope){
 myscope = window.myscope; //全局作用域
 return myscope;
}
alert(globalScope(’local’));

你甚至可以在循环中声明变量:

for(var i = 0; i < myarray.length; i++){}

覆盖函数/重载函数

当你不止一次的声明一个函数时,这个函数的最后一次声明将覆盖掉该函数的所有前面版本且不会抛出任何错误或警告。这不同于其他的编程语言,像Java,你能用相同的名字有多重函数,只要它们有不同的参数:调用函数重载。在JavaScript中没有重载。这使得不能在代码中使用JavaScript核心部分的名字极其重要。也要当心包含的多个JavaScript文件,像一个包含的脚本文件可能覆盖另一个脚本文件中的函数。请使用匿名函数和名字空间。

(function(){
 // creation of my namespace 创建我的名字空间
 if(!window.MYNAMESPACE) {
  window['MYNAMESPACE'] = {};
 }
 //如果名字空间不存在,就创建它
 //这个函数仅能在匿名函数中访问
 function myFunction(var1, var2){
  //内部的函数代码在这儿
 }
 // 把内部函数连接到名字空间上,使它通过使用名字空间能访问匿名函数的外面 
 window['MYNAMESPACE']['myFunction'] = myFunction;
})(); // 圆括号 = 立即执行
// 包含所有代码的圆括号使函数匿名

这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看《Javascript的匿名函数》YUI整个库只有YAHOO和YAHOO_config两个全局变量,它正是大量应用匿名函数和命名空间的方法来实现,具体请看《Javascript的一种模块模式》

字符串替换

一个常见错误是假设字符串替换方法的行为会对所有可能匹配都产生影响。实际上,JavaScript字符串替换只改变了第一次发生的地方。为了替换所有发生的地方,你需要设置全局标识。同时需要记住String.replace()的第一个参数是一个正则表达式。

var myString = "this is my string";
myString = myString.replace("","%20"); // "this%20is my string"
myString = myString.replace(/ /,"%20"); // "this%20is my string"
myString = myString.replace(/ /g,"%20"); // "this%20is%20my%20string"

parseInt

在JavaScript得到整数的最常见错误是假设parseInt返回的整数是基于10进制的。别忘记第二个参数基数,它能是从2到36之间的任何值。为了确保你不会弄错,请一直包含第二个参数。

parseInt('09/10/08'); //0
parseInt(’09/10/08′,10); //9, 它最可能是你想从一个日期中得到的值

如果parseInt没有提供第二个参数,则前缀为 ‘0x’ 的字符串被当作十六进制,前缀为 ‘0′ 的字符串被当作八进制。所有其它字符串都被当作是十进制的。如果 numString 的前缀不能解释为整数,则返回 NaN(而不是数字)。

‘this’

另一个常见的错误是忘记使用“this”。在JavaScript对象中定义的函数访问这个对象的属性,但没有使用引用标识符“this”。例如,下面是错误的:

function myFunction() {
 var myObject = {
  objProperty: "some text",
  objMethod: function() {
   alert(objProperty);
  }
 };
 myObject.objMethod();
} 

function myFunction() {
 var myObject = {
  objProperty: "some text",
  objMethod: function() {
   alert(this.objProperty);
  }
 };
 myObject.objMethod();
}

有一篇A List Apart文章用通俗易懂的英文表达了this绑定的问题。

对this使用最大的陷阱是this在使用过程中其引用会发生改变:

<input type="button" value="Gotcha!" id="MyButton">
<script>
var MyObject = function () {
    this.alertMessage = "Javascript rules";
    this.ClickHandler = function() {
        alert(this.alertMessage );
        //返回结果不是”JavaScript rules”,执行MyObject.ClickHandler时,
        //this的引用实际上指向的是document.getElementById("theText")的引用
  }
}();
document.getElementById(”theText”).onclick =  MyObject.ClickHandler
</script>

其解决方案是:


var MyObject = function () {
    var self = this;
    this.alertMessage = “Javascript rules”;
    this.OnClick = function() {
        alert(self.value);
    }
}();

类似问题的更多细节和解决方案请看《JavaScript作用域的问题》

遗漏的参数

当给函数增加一个参数时,一个常见的错误是忘记更新这个函数的所有调用。如果你需要在已经被调用的函数中增加一个参数来处理一个特殊情况下的调用,请给这个函数中的这个参数设置默认值,以防万一在众多脚本中的众多调用中的一个忘记更新。

function addressFunction(address, city, state, country){
 country = country || “US”; //如果没有传入country,假设 “US”
 span>//剩下代码
}

你也能通过获取arguments来解决。但是在这篇文章我们的注意力在陷阱上。同时在《Javascript风格要素(2)》也介绍了||巧妙应用。

for语句

在JavaScript中“for”循环将遍历所有的对象属性(attribute),包括方法和属性(property)。决不能使用for in来遍历数组:仅在当需要遍历对象属性和方法时才使用for in。

  1. for(var myVar in myObject)用一个指定变量无任何规律地遍历对象的所有属性。如果for/in循环的主体删除了一个还没有枚举出的属性,那么该属性就不在枚举。如果循环主体定义了新属性,那么循环是否枚举该属性则是由JavaScript的实现决定。
  2. for(var 1=0; i < myArray.length; i++)会遍历完一个数组的所有元素。

为了解决这个问题,大体上你可以对对象使用 for … in,对数组使用for循环:

listItems = document.getElementsByTagName('li');
for (var listitem in listItems){
 //这里将遍历这个对象的所有属性和方法,包括原生的方法和属性,但不遍历这个数组:出错了!
}
//因为你要循环的是数组对象,所用for循环
for ( var i = 0; i < listItems.length; i++) {
 //这是真正你想要的
}

对象的有些属性以相同的方式标记成只读的、永久的或不可列举的,这些属性for/in无法枚举。实际上,for/in循环
会遍历所有对象的所有可能属性,包括函数和原型中的属性。所有修改原型属性可能对for/in循环带来致命的危害,所以需要采用hasOwnProperty和typeof做一些必要的过滤,最好是用for来代替for/in。

switch语句

Estelle Weyl写了一篇switch statement quirks,其要点是:

  1. 没有数据类型转换
  2. 一个匹配,所有的表达式都将执行直到后面的break或return语句执行
  3. 你可以对一个单独语句块使用多个case从句

undefined ≠ null

null是一个对象,undefined是一个属性、方法或变量。存在null是因为对象被定义。如果对象没有被定义,而测试它是否是null,但因为没有被定义,它无法测试到,而且会抛出错误。

if(myObject !== null  && typeof(myObject) !== 'undefined') {
 //如果myObject是undefined,它不能测试是否为null,而且还会抛出错误
}
if(typeof(myObject) !== 'undefined' && myObject !== null) {
 //处理myObject的代码
}

Harish Mallipeddi对undefined和null有一个说明。

事件处理陷阱

刚接触事件处理时最常见的写法就是类似:

window.onclick = MyOnClickMethod

这种做法不仅非常容易出现后面的window.onclick事件覆盖掉前面的事件,还可能导致大名顶顶的IE内存泄露问题。为了解决类似问题,4年前Simon Willison就写出了很流行的addLoadEvent():

function addLoadEvent(func) {
 var oldonload = window.onload;
 if (typeof window.onload != 'function') {
  window.onload = func;
 }else {
  window.onload = function() {
   oldonload();
   unc();
  }
 }
}
addEvent(window,'load',func1,false);
addEvent(window,'load',func2,false);
addEvent(window,'load',func3,false);

当然在JavaScript库盛行的现在,使用封装好的事件处理机制是一个很好的选择,比如在YUI中就可以这样写:

YAHOO.util.Event.addListener(window, "click", MyOnClickMethod);


{十月 16, 2008}   函数两种定义方法的区别
在看黑羽的大作《as3 殿堂之路的时候》,看到黑羽对as中的函数定义的两种方法做了一个比较。觉得很受用。那么它是不是也适用于as的兄弟语言js呢?做了个实验。详解如下:

在as/js中定义一个函数有两种方法。

方法1:
function funName()
{

}

方法2:
var funName = function()
{

}

这两种方法在一般的使用中是没有太大区别的。但还是会有所不同。

首先,方法1方式定义的函数,调用的语句可以写在函数定义之前,而方法2方式定义的函数,调用只能写在定义之后。

下面是一个小demo:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
</head>
<script type="text/javascript">
testA();
testB();
function testA()
{
    alert("a");
}
var testB = function()
{
    alert("b");
}
</script>
<body>
</body>
</html>

程序在成功调用testA之后,就报错了。FF下提示说testB函数未定义。如果把testB的调用放到testB的定义后面,则正常调用。



{十月 16, 2008}   YUI中js的继承示例
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script type="text/javascript" src="http://cn.yimg.com/i/yui/2.5.2/build/yahoo-dom-event/yahoo-dom-event.js"></script>
</head>
<script type="text/javascript">
function RichWin()
{
    this.tpl = "adang";
    this.alert = function(){alert(this.tpl)};
    var testStr = "hello world";
    this.show = function(){alert(testStr)};
}

function Tool_common()
{
    this.constructor.superclass.constructor.call(this);
    this.type = "tool_common";
}
YAHOO.lang.extend(Tool_common,RichWin);

var obj = new Tool_common();
alert(obj.testStr);
obj.show();
</script>
<body>
</body>
</html>

一个简单的例子。在这个例子中,可以看到,用var 定义的私有变量,是不能被继承的。所有能被继承的,一定是通过this关键字,在内在地址中和这个对象的地址捆在一起的变量。因为复合对象传的不是值而是址,所以通过一个公开的方法,方法内部调用私有属性,来间接访问私有变量。这一点和正式的oop语言倒是没两样。



{十月 08, 2008}   [转载] 美国人眼里的中国----来自美国兰德公司《中国现状分析报告》
美国兰德公司是一家著名的非盈利的研究机构,为美国官方提供“客观的分析和有效的解决方案”。最近,他们公布了一份对中国现状分析报告,即有肯定,也有严厉批评,值得国人反省。本文观点来自兰德公司亚太政策中心。    
如果20世纪的中国是一个富裕和统一的国家,我们会有一个完全不同的第一次世界大战,我们就不会有第二次世界大战而是第二次欧洲大战。中国能够 阻止日本侵略或者打败日本。美国在这些冲突上的花费从根本意义上会减少很多,因为珍珠港事件不会发生。我们和整个世界,更不用说10亿中国人,一个多世纪 以来,已经为中国的弱小付出了惨重的代价。世界需要一个健康的中国。   
中国的需求对日本走出衰退起到了促进作用。日本状况给世界 经济带来了风险。关于这一点,怎么说都不夸张。日本巨额的债务会产生多米诺骨牌效应,逐渐波及到全世界。在中国有力的帮助下,危险似乎已经过去。中国全球 化给美国带来了很多影响。最明显的是,中国成为美国商品最大的市场。    
可口可乐早就完成了那个看上去像是神话的目标:卖10亿瓶可口可乐;曾经嘲笑中国梦的通用在中国卖了很多的别克汽车,在困难时期,中国带来的利润占通用利润的很大一部分;中国联想购买
IBM个人电脑业务,挽救了这个垂死部门的工作岗位。中国提供更低价的生活必需品给美国人的生活水平做出了很大的贡献,尤其是对我们不是那么富裕的居民而言。有迹象表明由于能够购买中国低价的出口货物,低收入美国人的生活水平可能提高了5%到10%。    
中国金融体系的不合理意味著中国建造了垂死企业,导致巨大的生产力过剩。近些年来,中国财政政策上的反复无常导致过度建造,对铁、铝、水泥和其 他原材料产生了巨大的需求。日本人和现在的中国人看上去似乎会买下世界上所有的东西,但是当你看到他们的财政状况的潜在问题时,你会发现一个黑洞。日本人 在90年代陷入了这样一个黑洞,至今还在努力地爬出来。中国人很多年后仍将会为目前这种无节制的狂热的购买行为感到心痛。    
目 前,中国面临著巨大的挑战。中国的银行是我们所知道的世界上最糟糕的银行。中国每一代,都有相当于美国规模的人口从农村涌入城市。每年,都有1200— 1300万新工人加入就业大军。在制造业,生产力对就业的影响比我们国家要严重得多。到2020年,中国人口老龄化会使工作人口与不工作人口的比率成为世 界上最糟糕的,比日本更甚。如果没有特效的新政策的话,中国的经济在那个时期就会狠狠地撞墙。到2020年,以我们的标准来看,它会是一个非常穷的国家。     
中国人缺乏诚信和社会责任感。中国人不了解他们作为社会个体应该对国家和社会所承担的责任和义务。普通中国人通常只关心他们 的家庭和亲属,中国的文化是建立在家族血缘关系上而不是建立在一个理性的社会基础之上。中国人只在乎他们直系亲属的福址,对与自己毫不相关的人所遭受的苦 难则视而不见。毫无疑问,这种以血缘关系为基础的道德观势必导致自私,冷酷,这种自私和冷酷已经成为阻碍中国社会向前发展的最关键因素。    
中国从来就没有成为一个法制社会,因为中国人的思维方式与守法行为格格不入。中国人老想走捷径。他们不明白这样一个事实:即成就来自于与努力工 作和牺牲。中国人倾向于索取而不给予。他们需要明白一个道理:生活的真蒂不在于你你索取多少而在于你能给予社会和你的人类同胞多少。    
大多数中国人从来就没有学到过什么是体面和尊敬的生活意义。中国人普遍不懂得如何为了个人和社会的福址去进行富有成效的生活。潜意识里,中国人视 他们的生活目的就是抬高自己从而获得别人的认知。这样一来,一个人就会对“保有面子”这样微不足道欲望感到满足。“面子”是中国人心理最基本的组成部分, 它已经成为了中国人难以克服的障碍,阻碍中国人接受真理并尝试富有意义的生活。 
这个应受谴责的习性使得中国人生来就具有无情和自私的特点,它已成为中国落后的主要原因。    
中国人没有勇气追求他们认为正确的事情。首先,他们没有从错误中筛选正确事物的能力,因为他们的思想被贪婪所占据。再有,就算他们有能力筛选出正确的事情,他们也缺乏勇气把真理化为实践。    
中国人习惯接受廉价和免费的事物,他们总是梦想奇迹或者好运,因为他们不愿意付出努力,他们总想不劳而获。很少有中国人明白一个事实,就是威望 和成就是通过一步步努力的工作和牺牲实现的,不付出就没有所得。简单来说,如果是为了谋生,那一个人只有去索取;但如果是为了生活,一个人必须要去奉献。    
由于在贫穷的环境下生长并且缺少应有的教育,大多数中国人不懂得优雅的举止和基本的礼貌。他们中的大多数人着装笨拙粗鄙却不感到害羞。他们在青少年时所受的教育就是如何说谎并从别人那里索取,而不是去与别人去分享自己的所有。
中国是一个物产丰富的国家。但无限制生育政策所带来恶果使得中国成为了无限廉价劳动力的输出国。这些输出也包括那些受过教育的劳力输出,除了他们的教育水平,实则和其他一般苦力没有本质上的区别。    
中国大规模生产的便宜产品降低了输入这些产品的地区的商业信用度。由于技术落后,管理失败,中国制造的单位能耗要比发达国家如日本,美国高出很 多。因此,随着出口额的增加,中国在扩大生产的同时丧失着宝贵的能源。同时,这种行为也严重的污染了环境,使中国变为全世界最不适宜人类居住的国家。  
目前中国正在遭受着资本主义社会两大邪恶的折磨,即环境的破坏与人性的丧失。由于中国人天生的贪婪的本性,它们可以毫无保留的接受资本主义的阴 暗面即无止境的追求利润,忽视人的尊严。中国人对西方的技术与产品狂热追求却对西方管理文化所强调的坦率,直接,诚实这些品质漠不关心。
由于中国文化不鼓励敢于冒险这种优良品质,所以中国人极力避免冒险,他们也不想寻求机会来改善自己的生活。中国人对于生活的平衡性和意义性并不感兴 趣,相反他们更执迷于对物质的索取,这点上要远远胜于西方人。大多数中国人发现他们不懂得"精神灵性","自由信仰"以及"心智健康"这样的概念,因为他 们的思想尚不能达到一个生命(补:即肉体和灵性的并存)存在的更高层次。他们的思想还停留在专注于动物本能对性和食物那点贪婪可怜的欲望上。 
在中国人的眼中,受教育不是为了寻求真理或者改善生活质量,而只是身份和显赫地位的象征和标志。中国的知识分子从别人那里得到尊敬并不是因为他 们为了别人的幸福做过什么,而只是因为他们获得占有了相当的知识。事实上,他们中的大多数只不过是一群仅仅通晓考试却从不关心真理和道德的食客。 
中国的教育体系很大程度上已经成为一种失败和耻辱。它已经不能够服务于教育本应所服务的对象:社会。这个教育体系不能提供给社会许多有用的个体。它只是制造出一群投机分子,他们渴望能够受益于社会所提供的好处却毫不关心回报。
中国可以培养出大批的高级能人才,但却很少可以培养出合格的可以独立主持的管理级专家。服务于一个公司或者社会,光有技术是不够的;还需要有勇 气,胆量,正直和诚实的领导才能,这恰恰是大多数中国人所缺少的品性。正如亚瑟、史密斯,一位著名的西方传教士一个世纪前所指出的,中国人最缺乏的不是智 慧,而是勇气和正直的纯正品性。这个评价,虽然历经百年,如今依旧准确诊断出中国综合症的病因。   
大多数中国毕业生对选择出国并为外国工作不会感到内疚,事实上他们首先欠下了中国人民在教育上为他们所做出的牺牲。随着传统文化价值观的破坏和逐步衰弱,大多数的中国人,包括受过教育的人都徘徊在精神和内心世界的路口,像迷失方向的人一样不知何去何从。



about

打造高品质的前端代码

pages
categories
archive
et cetera