2008年11月13日


作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/39669  发表时间: 2006年12月20日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

引自:http://www.blogjava.net/renyangok/archive/2006/12/12/87183.html
深入理解abstract class和interface
abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此很多开发者在进行抽象类定义时对于abstract class和interface的选择显得比较随意。其实,两者之间还是有很大的区别的,对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析,试图给开发者提供一个在二者之间进行选择的依据。

理解抽象类

abstract class和interface在Java语言中都是用来进行抽象类(本文中的抽象类并非从abstract class翻译而来,它表示的是一个抽象体,而abstract class为Java语言中用于定义抽象类的一种方法,请读者注意区分)定义的,那么什么是抽象类,使用抽象类能为我们带来什么好处呢?

在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。比如:如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。

在面向对象领域,抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生,也可扩展此模块的行为功能。熟悉OCP的读者一定知道,为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle),抽象类是其中的关键所在。


从语法定义层面看abstract class和interface

在语法层面,Java语言对于abstract class和interface给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。

使用abstract class的方式定义Demo抽象类的方式如下:

abstract class Demo { 
abstract void method1(); 
abstract void method2(); 
… 
}


使用interface的方式定义Demo抽象类的方式如下:

interface Demo { 
void method1(); 
void method2(); 
… 
}


在abstract class方式中,Demo可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface方式的实现中,Demo只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract的。从某种意义上说,interface是一种特殊形式的abstract class。

从编程的角度来看,abstract class和interface都可以用来实现"design by contract"的思想。但是在具体的使用上面还是有一些区别的。

首先,abstract class在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。

其次,在abstract class的定义中,我们可以赋予方法的默认行为。但是在interface的定义中,方法却不能拥有默认行为,为了绕过这个限制,必须使用委托,但是这会 增加一些复杂性,有时会造成很大的麻烦。

在抽象类中不能定义默认行为还存在另一个比较严重的问题,那就是可能会造成维护上的麻烦。因为如果后来想修改类的界面(一般通过abstract class或者interface来表示)以适应新的情况(比如,添加新的方法或者给已用的方法中添加新的参数)时,就会非常的麻烦,可能要花费很多的时间(对于派生类很多的情况,尤为如此)。但是如果界面是通过abstract class来实现的,那么可能就只需要修改定义在abstract class中的默认行为就可以了。

同样,如果不能在抽象类中定义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了"one rule,one place"原则,造成代码重复,同样不利于以后的维护。因此,在abstract class和interface间进行选择时要非常的小心。


从设计理念层面看abstract class和interface

上面主要从语法定义和编程的角度论述了abstract class和interface的区别,这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面:abstract class和interface所反映出的设计理念,来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概念的本质所在。

前面已经提到过,abstarct class在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is a"关系,即父类和派生类在概念本质上应该是相同的(参考文献〔3〕中有关于"is a"关系的大篇幅深入的论述,有兴趣的读者可以参考)。对于interface 来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。

考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:

使用abstract class方式定义Door:

abstract class Door { 
abstract void open(); 
abstract void close(); 
} 



使用interface方式定义Door:


interface Door { 
void open(); 
void close(); 
} 



其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。

如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中,主要是为了展示abstract class和interface反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略)?下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。

解决方案一:

简单的在Door的定义中增加一个alarm方法,如下:

abstract class Door { 
abstract void open(); 
abstract void close(); 
abstract void alarm(); 
} 


或者

interface Door { 
void open(); 
void close(); 
void alarm(); 
} 



那么具有报警功能的AlarmDoor的定义方式如下:

class AlarmDoor extends Door { 
void open() { … } 
void close() { … } 
void alarm() { … } 
} 



或者

class AlarmDoor implements Door { 
void open() { … } 
void close() { … } 
void alarm() { … } 
} 


这种方法违反了面向对象设计中的一个核心原则ISP(Interface Segregation Priciple),在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变(比如:修改alarm方法的参数)而改变,反之依然。

解决方案二:

既然open、close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用abstract class方式定义;两个概念都使用interface方式定义;一个概念使用abstract class方式定义,另一个概念使用interface方式定义。

显然,由于Java语言不支持多重继承,所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。

如果两个概念都使用interface方式来定义,那么就反映出两个问题:1、我们可能没有理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用interface方式定义)反映不出上述含义。

如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系在本质上是"is a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:

abstract class Door { 
abstract void open(); 
abstract void close(); 
} 
interface Alarm { 
void alarm(); 
} 
class AlarmDoor extends Door implements Alarm { 
void open() { … } 
void close() { … } 
void alarm() { … } 
}



这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实abstract class表示的是"is a"关系,interface表示的是"like a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。



结论

abstract class和interface是Java语言中的两种定义抽象类的方式,它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理,因为它们表现了概念间的不同的关系(虽然都能够实现需求的功能)。这其实也是语言的一种的惯用法


已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/39669
posted @ 2008-11-13 10:10 前 阅读(21) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/41255  发表时间: 2006年12月28日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

  现在进入了WEB2.0时代,AJAX的应用也将无处不在,紧随其后的ajax ToolKit也相继出现DOJO、YahooUI...等非常强大的面向对象的JavaScript的工具箱,
对于你方便阅读Source,最好能够了解一下JavaScript下如何使用OO进行编程的, 这有很大的用处,以下偶提供的小例讲述了JS OO编程的简单应用

<html>
	<head>
		<title></title>
		
		<script>
			function ClassTest1(){
       alert("Congratulation! this frist class build success!");
     }

   function aa(){
    var a=new ClassTest1();
  }


    function ClassTest2(var1){
      alert(var1);

    }

    var b=new ClassTest2("hello");

  //构建一个class并构造一个name属性
  function ClassTest3(name){
  	this.name = name;
  }
  
  /*ClassTest3的成员方法*/
  ClassTest3.prototype.sayHello = function () {
   alert("Hello " + this.name);
}
  function newClassTest3(){
  	//实例化类class3
  	var class3 = new ClassTest3("class3name");
  	class3.sayHello();
  	//创建一个age属性并对其付值 

  	class3.age = 1;
  	alert(class3.age);
  	/*创建一个address.home属性并对其付值(与许多
  	面对象的语言一样JS也可以像用‘.’一样来用‘[]’来引用来
  	属性,主要是为了避免带'.'的属性)*/
  	class3['address.home'] = "shijiazhuang";
  	alert(class3['address.home']);
  }

			</script>
			
			
			<script language="javascript" type="text/javascript">
//我们可以通过for in循环来遍历对象的属性。

var testObj = {

prop1 : "hello",
prop2 : "hello2",
prop3 : new Array("hello",1,2)
}

for(x in testObj) alert( x + "-" + testObj[ x ] )

//-->
</script>

<SCRIPT LANGUAGE="javascript">
<!--
var Circle = { x : 0, y : 1, radius: 2 } // another example

for(p in Circle) 
alert( p + "-" + Circle[ p ] )


</SCRIPT>

	</head>
<body>
		<input type="button" onclick="aa()"/>
		<input type="button" onclick="newClassTest3()"/>
</body>
</html>


已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/41255
posted @ 2008-11-13 10:10 前 阅读(24) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/47676  发表时间: 2007年01月16日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

补格助词当中,に和で的用法是最多的。这里专门介绍一下に的用法。在学习的初期,这些内容不一定都能明白,学习多少能理解多少就可以了。尤其是最后一部分内容,已经是属于中级知识范围了。
1,存在的地点
  存在句有2种格式:
① 教室に(补语)机が(主语)あります(谓语)。
这是补主谓结构,あります译成“有”。全句译成“教室里有桌子。”
② 机は(主语)教室に(补语)あります(谓语)。
这是主补谓结构,あります译成“在”。全句译成“桌子在教室里。”
  不论在哪种存在句,物体存在的地点,都用“に”表示,称作“存在的地点”。另外,存在句中还有个问题是:人和动物用いる、います。其存在地点仍然用“に”表示。

2,具体时间
  在中表示时间有2种:一个是象今日(きょう)、去年(きょねん)、来週(らいしゅう)、今朝(けさ)、夕べ(ゆうべ)等等单个的时间名词。另一个是年、月、时、星期等等直接有数词的时间名词,称作“具体时间”。用具体时间时后面要加“に”。
如:「私は今朝(单个的时间名词)6時に(具体时间名词)起きました。」
“ 我今天早晨6点钟起床了。”
「山田さんは1998年に(具体时间名词)大学を卒業しました。」
“山田先生在1998年大学毕业了。”
「水曜日に(具体时间名词)テストがあります。」
“星期三有考试。”

3,动作的对象
  英语的及物动词做谓语的句子中有双宾语,即直接宾语和间接宾语。中没有间接宾语,英语的间接宾语在中用带に的补语表示,就是“动作的对象”用带に的补语表示。
「先生は学生に(对象)日本語を教えます。」
“老师教学生。”
「私は田中さんに(对象)手紙を出しました。」
“我给田中发了信。”

4,动作的落脚点
  “落脚点”的概念容易和“对象”混淆。“对象”应该是人或者是动物之类有生命的东西;而“落脚点”是动作的归宿。
「李さんは朝早く教室に(落脚点)来ました。」
“小李一大早就来到教室。”
「バスに(落脚点)乗って会社へ行きます。」“乘公共汽车去公司。”
「先生は黒板に(落脚点)字を書きます。」“老师往黑板上写字。”
「この用紙に(落脚点)名前と電話番号を書いてください。」
“请在这张表格上写上姓名和电话号码。”

5,移动的方向
  一般移动方向用“へ”表示。而这时的へ可以用に代替。
「明日ペキンに(移动方向)行きます。」
“明天我去北京。”
「来年アメリカに(移动方向)留学します」
“明年我去美国留学。”

6,变化结果
  事物经过变化,由一种事物变成了另一种事物。这里有2种情况:
① 客观地描述事物的变化,或者说客观地力量促使了事物的变化,用“名词+になる”的形式。
「大学を卒業して、教師に(变化结果)なりました。」
“大学毕业后,当了教师。”
「出張でシャンハイに行くことに(变化结果)なった。」
“因为出差,要去上海了。”
② 经过自己主观努力完成了这个变化,用“名词+にする”的形式。
「来週海外へ旅行に行く事にしました。」
“决定下周去海外旅行。”
「今後火曜日を日本語の勉強日にする。」
“我决定今后把星期二定为学习日。”
③用 “名词+になっている”和“名词+にしている”的形式来分别表示“规定和制度”以及“自己决定后一直执行”。
「学校は、夜12時に校門を閉める事になっている。」
“学校规定午夜12时关门。”
「私は毎日2時間日本語を勉強する事にしている。」
“我每天都学习2小时。”

7,来去的目的
  在移动动词的前面表示移动的目的,名词或动词连用形后面加 に再加动词。
「町へ買い物に(移动的目的)行きます。」
“上街去买东西。”
「レストランへ食事をしに(移动的目的)行きます。」
“去餐馆吃饭。”
「忘れ物を取りに(移动的目的)家へ帰りました。」
“回家去取忘遗忘了的东西。”
「先生の授業を聞きに(移动的目的)学校に来ました。」
“到学校来听老师讲课。”

8,比较的对象
  这个形式主要用于进行比较。但是和“より”不同,是表示对于一些事物的自己的能力。
「私は寒さに強い。」
“我不怕冷。”
「あの人は酒に強い。」
“那个人酒量大。”
「彼は自分に厳しい。」
“他对自己很严格。”
「あの母親は子供に甘い。」
“那个母亲对孩子太溺爱。”
「私は歴史に弱い。」
“我不擅长历史。”
  从这些例句可以看出:虽然日语的形式是基本相同的,但是翻译成为中文后就很不一样了。这里就有日语有日语的形式,中文有中文的形式,绝对不是一样的。

9,表示动作或状态的原因
  一般认为で表示原因,但是用に表示原因和で不一样,是专门用于引起心理的和生理的现象的动作之前,强调内在原因。
「余りの可笑しさに、思わず笑い出した。」
“因为太可笑了,所以忍不住笑起来了。”
「長い間の勉强に疲れた。」
“由于长时间的学习而疲倦了。”
「生活に困る。」
“生活很困难。”

10,特殊动词的要求
  有一些动词,不遵守一般的格式,有其特殊的要求。如:“勤める(工作)”“住む(居住)”“泊まる(暂住)”等,虽然都是行为动词,但是其动作场所不用“で”而用“に”。(我估计还有一些动词属于这一类。)
「私は中国銀行に勤めています。」
“我在中国银行工作。”
「先生はウルムチに住んでいます。」
“老师住在乌鲁木齐。”
「ペキンでは北京飯店に泊まりました。」
“在北京,我住在北京饭店。”

11,被动式动作的主体
  在被动式的句子中,表示动作主体的词语,不用“は”“が”,而用“に”。
「弟は兄に(动作主体)殴られた。」
“弟弟被哥哥打了。”
「私は子供に(动作主体)時計を壊された。」
“我的表被孩子弄坏了。”
「雨に(动作主体)降られて風邪を引いた。」
“被雨淋了而感冒了。”

12,使役态动作的主体
  在使役态的他动词句子中,表示动作主体的词语,不用“は”“が”,而用“に”。(自动词句子中 ,表示动作主体的词语用“を”)
「先生は学生に本を読ませました。」
“老师让学生读书。”
「この仕事は私にさせてください。」
“这个工作请让我作吧。”

13,被役态的外界力量
  在被役态句子中,表示外界强迫的力量用“に”。
「私は妻に病院へ行かされました。」
“我被妻子逼着去了医院。”
「 私が飲みたいのではありません、飲まされたのです。」
“不是我想喝的,是他们灌我的。”


已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/47676
posted @ 2008-11-13 10:10 前 阅读(23) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/47677  发表时间: 2007年01月16日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

1 活动场所
在以行为动词为谓语的句子中,活动场所用で表示。
「私達は学校で(活动场所)勉強をします。」
“我们在学校学习。”
「運動場で(活动场所)運動会を開きます。」
“在运动场举行运动会。”

2 比较范围
事物进行比较时总是有一个比较的范围,经常说“在……范围内……。”这个比较范围用で表示。
「中国では(比较范围)、北京大学が一番有名です。」
“在中国,北京大学最有名。”
「私達のクラスでは(比较范围)、李さんが最も真面目です。」
“在我们班小李最认真。”

3 工具
当人做某种行为时,往往依赖于某些工具。在句子中直接表示所使用的工具,就用で表示。
「バスで(工具)会社に行きます。」
“乘公共汽车去公司。”
「万年筆で(工具)名前を書きます。」
“用钢笔写名字。”
「彼達は日本語で(工具)話しています。」
“他们用日语在交谈。”
这里注意:用で表示工具时,一定要直接在工具名词后面加で表示,不能加进动词。试比较:「バスに乗って会社に行きます。」这句话仍然译成“乘公共汽车去公司。”但是因为用了动词,表现方式就有了变化。

4 方式
主要是描述动作主体的数量。
「私は一人で(方式)住んでいます。」
“我一个人住着。”
「学生たちは五人で(方式)先生の家に行きました。」
“学生们五个人去了老师家。”
「皆で(方式)歌を歌いましょう。」
“大家一起唱歌吧。”

5 总和
和上一项不同,单价或者一个人的不加で,2个以上的合计值就要加で。
「靴下は一足5元です、3足で(合计)15元です。」
“袜子1双5元,3双就是15元。”
「一人3冊だと10人で(合计)30冊になります。」
“如果一个人3本,10个人就是30本。”
「一軒5m必要としたら、20軒で(合计)100m必要です。」
“如果一家需要5米,那么20家就需要100米。”

6 原因
表示构成后面情况的原因。
「地震で(原因)家が倒れました。」
“因为地震,房子倒了。”
「山田さんは病気で(原因)会社を休みました。」
“山田先生因为生病,请假没有上班。”
「事故で(原因)電車が遅れました。」
“因为事故,电车误点了。”
和表示工具的情况类似,这里必须是单独地使用“名词+で”,如果采用了动词,虽然意思没有发生变化,但是情况就完全不一样了。
「地震が起きて(原因)家が倒れました。」
「山田さんは病気になって(原因)会社を休みました。」
「事故が発生して(原因)電車が遅れました。」

7 材料
表示物体的构成原料或材料,可以用で表示。但是同时也可以用から表示。它们的没有严格的区别,但是一般认为,一个物体直接能看出原材料的(即物理变化)用で表示;如果已经看不出来原材料的(即化学变化),一般用から表示,但是在这样的情况下也可以用で表示。
「このテーブルは木で(原材料,即物理变化)作られています。」
“这个餐桌是由木材制作的。”
「米から(原材料,即化学变化)酒が作られます。」
“米可以造酒。”
另外,表示公共汽车或电车拥挤时,由于其原因是人造成的,人成了充满车厢内部的原料,所以人用表示。公路堵车也一样。
「バスの中は人で(原材料)ぎっしり詰まっています。」
“公共汽车里挤满了人。”
「道路は車で(原材料)渋滞です。」
“公路塞车了。”

8 时间限定
表示限定的时间用で表示。
「夏休みは明日で(时间限定)終わりです。」
“暑假明天结束。”
「一時間で(时间限定)30ページ読みました。」
“一个小时读了30页。”
「今日の授業はこれで(时间限定)終わります。」
“今天的课到此结束。”

9 特殊词汇要求:後で
有一些词汇,不符合一般规律,有特殊的要求。这里介绍要求で的词汇。
「前に、後で」表示时间,应该用に,但是表示在后面时,习惯地用で。
「日本の礼儀では、ご飯の前に‘頂きます’と言い、ご飯の後で(特殊要求)は‘御馳走様’と言う。これは、昔は神様に感謝していたが、今は食事を準備してくれた人に感謝する。」
“在日本的礼节中,吃饭前说‘我要吃了。’,吃饭后说‘吃饱了。’过去是对神表示感谢,现在是对准备了这餐饭的人表示感谢。”


除了补格助词で以外,在日语中有出现で的可能性有以下几种:
1 だ的连用形:中顿、否定
2个带有对比性或者相关的判断句并成一个句子的时候,前面句子的判断助动词だ就变成连用形で表示中顿。敬体的判断助动词です因为没有连用形で,所以借用だ的连用形で表示中顿。这里的で不是补格助词。
「田中さんは日本人です。」
“田中先生是日本人。”
「李さんは中国人です。」
“小李是中国人。”
「田中さんは日本人で(中顿)、李さんは中国人です。」
“田中先生是日本人,而小李是中国人。”
「これは私の鞄では(否定)ありません。」
“这个不是我的书包。”

2形容动词连用形之一
形容动词的词尾和判断助动词类似,是だ和です。其连用形之一是で。形容动词连用形で的用法很多,如并列、对比,连接,否定等等。注意这不是补格助词,其判断方法是で的前面是形容动词。
「公園は静かで、動物園は賑やかです。」
“公园里很安静,而动物园很热闹。”(并列、对比)
「此所は奇麗で静かな公園です。」
“这里是美丽而安静的公园。”(连接)
「デパートの中は、静かではありません。」
“百货公司里不安静。”(否定)

3接续助词て的浊化
接在动词连用形的后面构成连接式时,五段动词要音变,而且接续助词て要浊化变成で。
「私は毎日日本の小説を読んで(浊化)います。」
“我每天读日本的小说。”
「試験が終わったので、最近はのんびり遊んで(浊化)います」
“考试结束了,所以我悠闲的玩。”

4接续词で
接续词では有时简化成で。由于接续词一般都出现在句首,所以容易辨别。
「授業は終わりましたね。で(接续词)、後はどうしますか。」
“课程结束了。那么以后怎么办呐?”


已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/47677
posted @ 2008-11-13 10:10 前 阅读(23) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/47680  发表时间: 2007年01月16日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

先来看这个动词:

基本形:「頑張る」
ます形:「頑張ります」

给自己加油打气时可以说(自己对自己说):「頑張ります」、但在希望别人加油时,可不能这么用哦!看下面的:

先来看这个动词:

基本形:「頑張る」
ます形:「頑張ります」

给自己加油打气时可以说(自己对自己说):「頑張ります」、但在希望别人加油时,可不能这么用哦!看下面的:



1.「頑張れ」
动词的命令形,虽在语气上很不礼貌,女性使用的话更是粗鲁,但如果是在观看体育比赛,譬如在看世界杯,这种场合女性也可以用。

2.「頑張って(ね)」
动词て形,是日常生活中经常使用的表示祈使的说法,不论男性,女性都经常使用,但一般用于关系的人之间,比较适合于对于对方将来有某种期望,后续:「ね」更可使语气柔和(PS:美咲不太喜欢跟别人说:「頑張ってください」、虽然用「~てください」更加客气,但总觉得用在这种场合有点过分客气,很“怪”……用是可以用,而且很礼貌~~)

3.「頑張ろう」
动词的意志形,说话人当场表示自己的决心和意志,用在第二人称的时候解释为劝诱或建议,实际上,动词的意志形是「~ましょう」的简体形,所以呢,这里也能用「頑張りましょう」来“劝诱”对方加油。(带有自己和对方一起努力的语气)。「一緒に 頑張りましょう」(一起努力吧!)
……等

记得在不同的场合,不同的地位身份要用不同的说法哦!!


哦,对了,还有一个词,也带有加油的意思,好像是写「ファイート」,就是由英语里“fight”来的,可以给自己打气,我记得极道鲜师里,仲間由紀惠经常自己跟自己说「ファイート、オー」给自己打气呢!!
 




已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/47680
posted @ 2008-11-13 10:10 前 阅读(23) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/47701  发表时间: 2007年01月16日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

简单说,分了以下几点:

  1、格助词に表示静止的存在场所,格助词で表示动态的活动场所。

  例:庭に大きな木がある(静止)。
       私は教室で本を読む(动态)。

  2、强调动作场所时使用で,强调存在场所时使用に。

  例:花を庭で植える(强调种花的动作)。
       花を庭に植える(强调花种在院子里)。

  3、强调动作过程进行时用で,强调结果存在时用に。

  例:駅前の近くで家を建てている(强调建房子的动作在进行)。
       駅前の近くに家を建てている(强调房子已建成)。

  4、表长久性固定场所时用に,表暂时性偶然场所用で。

  例:駅に案内所がある(表询问处长期存在)。
       駅で集会がある(表有偶然暂时的集会)。

  5、内在地点用に,外在场所用で。

  例:彼女は銀行に勤めている(场所为谓语动词直接要求的对象)。
       彼女は上海で勤めている(场所为整个句子的内容所要求的背景)



已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/47701
posted @ 2008-11-13 10:10 前 阅读(22) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/48344  发表时间: 2007年01月18日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

frameName.doSomething()...

//访问父frame中方法
parent.frames["frameName"].doSomething()...

"frameName" 为要访问的frame名,doSomething()为要访问的frame中的方法。

已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/48344
posted @ 2008-11-13 10:10 前 阅读(19) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/53199  发表时间: 2007年02月08日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!


在Hibernate中,删除存在关联关系的一个对象时,会出现 org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)这个异常

解决方案如下:
方法1 删除Set方的cascade
方法2 解决关联关系后,再删除 :
   Attachment attachment = attachments.get(i);
   content.getAttachments().remove(attachment);
   attachment.setContent(null);
   removeObject(attachment);

方法3 在many-to-one方增加cascade 但值不能是none

如果以上三个方案都失败(哼哼~ 我用了5个小时才找出来的)
检查一下hashCode equals是否使用了id作为唯一标示的选项了;我用uuid.hex时是没有问题的;
但是用了native,就不行了,怎么办?删除啊!

也就是问题出现在本文给出的持久化类的hashCode equals方法身上

已有 1 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/53199
posted @ 2008-11-13 10:10 前 阅读(26) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/58268  发表时间: 2007年03月08日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="/common/taglibs.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<link type="text/css" rel="stylesheet"
href="<c:url value="/styles/dojoTable.css"/>">
</head>
<body>
<%@include file="/common/yahooUi.jsp"%>
<link type="text/css" rel="stylesheet" href="templates/dojo.css">
<link type="text/css" rel="stylesheet" href="<c:url value='/styles/style.css'/>">
<script src="<c:url value='/js/prototype.js'/>" type="text/javascript"></script>
<script src="<c:url value='/js/dojo/dojo.js'/>" type="text/javascript"></script>
<script src="<c:url value="/dwr/interface/deptDojoAction.js"/>"
type="text/javascript"></script>
<script src="<c:url value="/dwr/engine.js"/>" type="text/javascript"></script>
<script src="<c:url value="/dwr/util.js"/>" type="text/javascript"></script>

<script>
YAHOO.namespace("dept.dlg");

dojo.require("dojo.lang.*");
dojo.require("dojo.widget.Tree");
dojo.require("dojo.widget.TreeRPCController");
dojo.require("dojo.widget.TreeSelector");
dojo.require("dojo.widget.TreeNode");
dojo.require("dojo.widget.TreeContextMenu");

dojo.require("dojo.widget.*");
dojo.require("dojo.collections.*");
dojo.require("dojo.ex.FilteringTableEx");

/**
* 设置根目录style,并且加载第一级目录
*/
dojo.addOnLoad(function() {
  //初始化YahooUI对话框
  YAHOO.dept.dlg.Editor = new YAHOO.widget.Dialog("editDeptDlg", {visible:false,
                                                                    modal:true,
                                                                    shadow:false,
                                                                    close: true,
                                                                    fixedcenter : true ,
                                                                    width:"300px" } );
YAHOO.dept.dlg.Editor.render();
YAHOO.dept.dlg.manager = new YAHOO.widget.OverlayManager();
YAHOO.dept.dlg.manager.register([YAHOO.dept.dlg.Editor]);
YAHOO.dept.dlg.Editor.beforeHideEvent.fire = resetDlg;//对话框关闭之前的事件。
    //设置根节点style
    var rootNode = dojo.widget.manager.getWidgetById('root');
    rootNode.childIcon.style["width"] = "14px";
    rootNode.childIcon.style["height"] = "14px";
    //加载第一级目录
    loadRemoteChildren(rootNode);
 
    //注册菜单事件
    dojo.event.topic.subscribe('treeContextMenuCreate/engage',
function (menuItem) { createClicked( menuItem.getTreeNode()); });

    dojo.event.topic.subscribe('treeContextMenuRemove/engage',
        function (menuItem) { removeClicked( menuItem.getTreeNode()); });
       
    dojo.event.topic.subscribe('treeContextMenuEdit/engage',
        function (menuItem) { editClicked( menuItem.getTreeNode()); });
       
    dojo.event.topic.subscribe('treeContextMenuRefresh/engage',
        function (menuItem) { refreshClicked(menuItem.getTreeNode());});
  }
);

/**
* 新建部门菜单事件
*/
function createClicked(treeNode) {
  var dlgTextNode = document.getElementById("dlgHead");
  dlgTextNode.innerHTML = treeNode.title + '--' + '<fmt:message key="global.new" />';
 
  $('parentId').value = treeNode.objectId;
  $('treeNodeId').value = treeNode.widgetId;
   
  YAHOO.dept.dlg.Editor.show();
}



/**
* 编辑目录菜单事件
*/
function editClicked(treeNode) {
  deptDojoAction.get(treeNode.objectId, function(dept){
 
    var dlgTextNode = document.getElementById("dlgHead");
    dlgTextNode.innerHTML = treeNode.title + '--' + '<fmt:message key="global.edit" />';
   
    DWRUtil.setValue("treeNodeId", treeNode.widgetId);
    DWRUtil.setValue("name", dept.name);
    DWRUtil.setValue("id", dept.id);
    DWRUtil.setValue("descn",dept.descn);
   
    YAHOO.dept.dlg.Editor.show();
  });
}


/**
* 删除部门菜单事件
*/
function removeClicked(treeNode) { 
  if(confirm('<fmt:message key="global.delete.warn"/>')) {
    deptDojoAction.removeDept(treeNode.objectId,
      function() {
       if(!treeNode.children || treeNode.children.length == 0){
          treeNode.tree.removeNode(treeNode);
        } else {
          alert('<fmt:message key="dept.delete.warn"/>');
        }     
      }); 
  }
}

/**
* 在给定的父节点下,建立子节点.
*/
function buildChildNode(parent, nodeData) {
  node = dojo.widget.createWidget(parent.widgetType, nodeData);
  node.childIconSrc = '<c:url value="/images/icons/foldericon.png"/>';
  //isFolder是node一个内置属性,缺省为false在树中是不会显示的,为true时才会显示出来
  node.isFolder = true;
  parent.addChild(node);
  node.childIcon.style["width"] = "16px";
  node.childIcon.style["height"] = "16px";
 
  return node;
}


/**
* 根据给定的父节点,展开子节点。远程调用DWR函数。
*/
function loadRemoteChildren(parent) {

  deptDojoAction.getDeptsByParentId(parent.objectId, function(children) {
     for(var i=0; i<children.length; i++) {
       buildChildNode(parent, children[i]);
     }  
     parent.state = parent.loadStates.LOADED;
   });
   parent.expand();  
}
/**
* 展开子节点
*/
function getChildren(node, sync, callObj, callFunc) {
  nodeJSON = this.getInfo(node);
  var children = loadRemoteChildren(node);
  $('deptMsg').style.display = 'none';
}

/**
* 调用DWR函数,保存编辑结果
*/
function onSave() {

  var formValues = DWRUtil.getValues("editDeptFrm");
   
  if(formValues.id == "" || !formValues.id){//当id不存在时,表示新建
    deptDojoAction.saveDept(formValues.parentId,
      {name: formValues.name,
       descn: formValues.descn},
      function(newId) {
         var treeNode = dojo.widget.byId(formValues.treeNodeId);
         if(treeNode) {//当前节点下加入一个新节点
           if(treeNode.state == treeNode.loadStates.LOADED) {
              var child =
                  buildChildNode(treeNode, {title:formValues.name,
                                            objectId:newId,
                                            isFolder:true});
              //child.isFolder = true;
           }
         }
        
      });
   }
   else { //如果id存在则表示更新
     deptDojoAction.updateDept({id: formValues.id,
                                name: formValues.name,
                                descn: formValues.descn},
        function(id){
          var treeNode = dojo.widget.byId(formValues.treeNodeId);
            if(treeNode) {//更新节点
              treeNode.edit({title:formValues.name});
            }
       });
   }
  
   YAHOO.dept.dlg.Editor.hide();
}

/**
* 刷新树形节点
*/
function refreshClicked(node) {
  //更新当前节点
  deptDojoAction.get(node.objectId, function(dept) {
    node.edit({title: dept.name, objectId: dept.id})
  });
  //如果没有子节点,则直接返回
  if(!node.children || node.children.length == 0) {
    return;
  }
  //首先要删除所有子节点,删除的时候要将子节点们复制到一个数组
  //如果不这样,而采用dojo.lang.forEach(node.children...
  //则相当于修改了循环下标
  var nodes = new Array;
  for(i = 0; i < node.children.length; i ++) {
    //hasChildren用于标记节点是否已经展开,如果展开则加载子节点,但是,本次并未实现该功能
    nodes[i] = {body : node.children[i],   
                hasChildren : (node.children[i].chilren && node.children[i].chilren.length > 0)};
  }
  dojo.lang.forEach(nodes, function(elem){elem.body.tree.removeNode(elem.body);});
  //重新加载子节点
  loadRemoteChildren(node);
}
/**
* 移动(Drag and Drop)一个节点到新的节点下
*/
function moveNode(child, newParent, index) {
  alert("childId=" + child.objectId + ";\nnewParentId=" + newParent.objectId + ";\nIndex=" + index);
}

var files = new dojo.collections.ArrayList();

function dblselect(message) {
alert();
}
/**
* 选中一个节点的时候触发的事件。
*/
function onSelectNode(message) {
  var node = message.source;
  var e = message.event;
  var table = dojo.widget.byId('files');
  if(node) {
    //alert(node.objectId + node.object);
    $('deptMsg').style.display = 'block';
    //$('deptDesc').innerHTML =  node.object;
    DWRUtil.setValue('deptDesc',node.object);
    //var aa="";
    deptDojoAction.getDeptsNameByParentId(node.objectId, function(children) {
     for(var i=0; i<children.length; i++) {
       var file = {};
       file.filename = children[i];
       files.add(file);
     } 
     //alert(aa);
     table.store.setData(files.toArray());
     files.clear();
   });
  
  }
 
  doSelect(message, 'treeSelector');//使Tree恢复选中状态
}


/**
* Copy dojo的源代码,使得Tree恢复选中状态
*/
function doSelect(message, treeSelectorId) {
  var node = message.source;
  var e = message.event;
 
  var selector = dojo.widget.byId(treeSelectorId);
  if (selector.selectedNode === node) {
if(e.ctrlKey || e.shiftKey || e.metaKey){
selector.deselect();
return;
}
dojo.event.topic.publish(this.eventNames.dblselect, { node: node });
return;
}

if (selector.selectedNode) {
selector.deselect();
}
selector.doSelect(node);
dojo.event.topic.publish(selector.eventNames.select, {node: node} );
}

/**
* 复选框选中事件。选中复选框,则清空DatePicker
*/
function neverExpired(never) {
  if(never) {
    resetDataPicker();
  }
}


/**
* 重新设置对话框
*/
function resetDlg() {
  DWRUtil.setValues({parentId: "",
                     id: "",
                     treeNodeId: ""}, "editDeptFrm");
  DWRUtil.setValue("name", "");
  DWRUtil.setValue("descn","");
}
</script>
<table width="100%" cellspacing="10px" cellpadding="10px">
<tr>
<td width="50%" valign="top">
<table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#6290d2">
<tr><td bgcolor="#E8F2FE" height="20px"><fmt:message key='dept.tree'/></td></tr>
<tr>
<td style="padding-top:10px;padding-right:10px;" bgcolor="#ffffff">
<div dojoType="TreeRPCController" RPCUrl=""
widgetId="deptTreeController" DNDController="create"
loadRemote="getChildren" doMove="moveNode"></div>
<div dojoType="TreeSelector" widgetId="treeSelector"
select="onSelectNode" dblselect="dblselect"></div>
<!-- 上下文菜单 -->
<div dojoType="TreeContextMenu" toggle="explode"
contextMenuForWindow="false" widgetId="treeContextMenu"><!-- 新建目录 -->
<div dojoType="TreeMenuItem" treeActions="addChild"
iconSrc="<c:url value='/images/icons/folder_add.gif'/>"
widgetId="treeContextMenuCreate"
caption="<fmt:message key='global.new'/>"></div>
<!-- 删除目录 -->
<div dojoType="TreeMenuItem" treeActions="remove"
iconSrc="<c:url value='/images/icons/folder_remove.gif'/>"
widgetId="treeContextMenuRemove"
caption="<fmt:message key='global.remove'/>"></div>
<!-- 编辑目录 -->
<div dojoType="TreeMenuItem" treeActions="remove"
iconSrc="<c:url value='/images/icons/folder_edit.gif'/>"
widgetId="treeContextMenuEdit"
caption="<fmt:message key='global.edit'/>"></div>
<div dojoType="MenuSeparator2"></div>
<div dojoType="TreeMenuItem" widgetId="treeContextMenuRefresh"
caption="<fmt:message key='cms.refresh'/>"></div>
</div>

<!-- 树形目录 -->
<div dojoType="Tree" menu="treeContextMenu" DNDMode="between"
selector="treeSelector" widgetId="deptTree"
DNDAcceptTypes="deptTree" controller="deptTreeController"><!-- 树形目录根节点 -->
<div dojoType="TreeNode" title="<fmt:message key='dept.root'/>"
widgetId="root" isFolder="true"
childIconSrc="<c:url value='/images/icons/home_1.gif'/>" objectId="-1"></div>

</div>

<div id="editDeptDlg" style="visibility:hidden">
<div class="hd" id="dlgHead" style="font:12px"></div>
<div class="bd" id="dlgBody" style="font:12px">
  <form id="editDeptFrm" onsubmit="return false">
<input type="hidden" id="parentId" name="parentId"/>
<input type="hidden" id="id" name="id"/>
<input type="hidden" id="treeNodeId" name="treeNodeId"/>
    <br>
<table width="100%">
  <tr>
     <td width="20%" align="right"><fmt:message key="dept.name"/>:</td>
     <td><input id="name" name="name" type="text" size="28" class="thin-input"/></td>
     <td width=10%" align="left"><font color="#990000">*</font></td>
  </tr>
 
  <tr>
     <td width="20%" align="right"><fmt:message key="dept.descn"/>:</td>
     <td><textarea id="descn" name="descn" rows="3" cols="30" class="thin-input"></textarea></td>
     <td></td>
  </tr>  
 

  <tr>
  <td width="20%"></td>
    <td>
      <table>
        <tr>
          <td width="20%" align="right">
       <input type="button" value="<fmt:message key='global.save'/>"
        onclick="onSave()"/>
          </td>
          <td>
          </td>
         
        </tr>
      </table>
    </td>
  </tr>
</table>

</form>
</div>
<div class="ft" id="dlgFoot" style="font:12px;"></div>
</div>
</td>
</tr>
</table>
</td>

<td valign="top">

<table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#6290d2">
<tr><td bgcolor="#E8F2FE" height="20px" ><fmt:message key='dept.msg'/> : </td></tr>
<tr>
<td>
<div id="deptDesc" style="height:50px; border-width:10px; color='#003366'; border='1px solid #6290D2'; background-color: #ffffff"></div>


</td>
</tr>
<tr>


<td bgcolor="#ffffff">
<div id='deptMsg' class='dojoTable' style="display:none;">

<table dojoType="FilteringTableEx" widgetId="files" id="files" minRows="0"
valueField="filename" headerClass="tableHeader"
tbodyClass="tableBody" rowAlternateClass="odd"
headerUpClass="tableHeaderSort" headerDownClass="tableHeaderSort"
alternateRows="true" cellpadding="0" cellspacing="0" border="0"
class='tableRegion' style="width:100%">
<thead>
<tr>
   
<th field="filename" dataType="String" class="tableHeader" align="center" ><fmt:message key="dept.subList"/></th>

</tr>
</thead>
</table>
</div>

</td>
</tr>
</table>
</td>
</tr>
</table>


</body>
</html>


已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/58268
posted @ 2008-11-13 10:10 前 阅读(19) | 评论 (0)收藏

作者: toyota2006  链接:http://toyota2006.javaeye.com/blog/59311  发表时间: 2007年03月12日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

Javascript的IE和Firefox兼容性汇编

以下以 IE 代替 Internet Explorer,以 MF 代替 Mozzila Firefox。

document.form.item 问题

现有问题:
现有代码中存在许多 document.formName.item("itemName") 这样的语句,不能在 MF 下运行

解决方法:
改用 document.formName.elements["elementName"]

集合类对象问题

现有问题:
现有代码中许多集合类对象取用时使用 (),IE 能接受,MF 不能。

解决方法:
改用 [] 作为下标运算。如:document.forms("formName") 改为 document.forms["formName"]。
又如:document.getElementsByName("inputName")(1) 改为 document.getElementsByName("inputName")[1]

window.event

现有问题:
使用 window.event 无法在 MF 上运行

解决方法:
MF 的 event 只能在事件发生的现场使用,此问题暂无法解决。可以这样变通:

原代码(可在IE中运行):

<input type="button" name="someButton" value="提交" onclick="javascript:gotoSubmit()"/>
<script language="javascript">
    function gotoSubmit() {
       alert(window.event);    // use window.event
    }
</script>

新代码(可在IE和MF中运行):

<input type="button" name="someButton" value="提交" onclick="javascript:gotoSubmit(event)"/>
<script language="javascript">
   function gotoSubmit(evt) {
      evt = evt ? evt : (window.event ? window.event : null);
      alert(evt);             // use evt
  }
</script>

此外,如果新代码中第一行不改,与老代码一样的话(即 gotoSubmit 调用没有给参数),则仍然只能在IE中运行,但不会出错。所以,这种方案 tpl 部分仍与老代码兼容。

HTML 对象的 id 作为对象名的问题

现有问题:
在 IE 中,HTML 对象的 ID 可以作为 document 的下属对象变量名直接使用。在 MF 中不能。

解决方法:
用 getElementById("idName") 代替 idName 作为对象变量使用。

用idName字符串取得对象的问题

现有问题:
在IE中,利用 eval(idName) 可以取得 id 为 idName 的 HTML 对象,在MF 中不能。

解决方法:
用 getElementById(idName) 代替 eval(idName)。

变量名与某 HTML 对象 id 相同的问题

现有问题:
在 MF 中,因为对象 id 不作为 HTML 对象的名称,所以可以使用与 HTML 对象 id 相同的变量名,IE 中不能。

解决方法:
在声明变量时,一律加上 var ,以避免歧义,这样在 IE 中亦可正常运行。
此外,最好不要取与 HTML 对象 id 相同的变量名,以减少错误。

event.x 与 event.y 问题

现有问题:
在IE 中,event 对象有 x, y 属性,MF中没有。

解决方法:
在MF中,与event.x 等效的是 event.pageX。但event.pageX IE中没有。
故采用 event.clientX 代替 event.x。在IE 中也有这个变量。
event.clientX 与 event.pageX 有微妙的差别(当整个页面有滚动条的时候),不过大多数时候是等效的。

如果要完全一样,可以稍麻烦些:
mX = event.x ? event.x : event.pageX;
然后用 mX 代替 event.x

其它:
event.layerX 在 IE 与 MF 中都有,具体意义有无差别尚未试验。

关于frame

现有问题:
在 IE中 可以用window.testFrame取得该frame,mf中不行

解决方法:
在frame的使用方面mf和ie的最主要的区别是:
如果在frame标签中书写了以下属性:
<frame src="/xx.htm" id="frameId" name="frameName" />
那么ie可以通过id或者name访问这个frame对应的window对象
而mf只可以通过name来访问这个frame对应的window对象
例如如果上述frame标签写在最上层的window里面的htm里面,那么可以这样访问
ie: window.top.frameId或者window.top.frameName来访问这个window对象
mf: 只能这样window.top.frameName来访问这个window对象

另外,在mf和ie中都可以使用window.top.document.getElementById("frameId")来访问frame标签
并且可以通过window.top.document.getElementById("testFrame").src = 'xx.htm'来切换frame的内容
也都可以通过window.top.frameName.location = 'xx.htm'来切换frame的内容

在mf中,自己定义的属性必须getAttribute()取得

父结点的问题

在mf中没有 parentElement parement.children  而用 parentNode parentNode.childNodes
childNodes的下标的含义在IE和MF中不同,MF使用DOM规范,childNodes中会插入空白文本节点。
一般可以通过node.getElementsByTagName()来回避这个问题。当html中节点缺失时,IE和MF对parentNode的解释不同,例如

<form>
<table>
  <input/>
</table>
</form>

MF中input.parentNode的值为form, 而IE中input.parentNode的值为空节点
MF中节点没有removeNode方法,必须使用如下方法 node.parentNode.removeChild(node)

const 问题

现有问题:
在 IE 中不能使用 const 关键字。如 const constVar = 32; 在IE中这是语法错误。

解决方法:
不使用 const ,以 var 代替。

body 对象

MF的body在body标签没有被浏览器完全读入之前就存在,而IE则必须在body完全被读入之后才存在

url encoding

在js中如果书写url就直接写&不要写&amp;例如var url = 'xx.jsp?objectName=xx&amp;objectEvent=xxx';
frm.action = url那么很有可能url不会被正常显示以至于参数没有正确的传到服务器
一般会服务器报错参数没有找到
当然如果是在tpl中例外,因为tpl中符合xml规范,要求&书写为&amp;
一般MF无法识别js中的&amp;

nodeName 和 tagName 问题

现有问题:
在MF中,所有节点均有 nodeName 值,但 textNode 没有 tagName 值。在 IE 中,nodeName 的使用好象
有问题(具体情况没有测试,但我的IE已经死了好几次)。

解决方法:
使用 tagName,但应检测其是否为空。

元素属性

IE下 input.type属性为只读,但是MF下可以修改

document.getElementsByName() 和 document.all[name] 的问题

现有问题:
在 IE 中,getElementsByName()、document.all[name] 均不能用来取得 div 元素(是否还有其它不能取的元素还不知道)。


已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




文章来源:http://toyota2006.javaeye.com/blog/59311
posted @ 2008-11-13 10:10 前 阅读(19) | 评论 (0)收藏
仅列出标题  

导航

<2025年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

统计

留言簿(25)

搜索

最新评论