准备编写JSI的外围元素,先整理一下编码风格和一些约定,欢迎大家讨论。

基本风格

    * 基本参照Java代码风格。
         1. 驼峰式命名(单词无连接字符,单词首字母大写,其余小写);
         2. 类的首字母大写(eg:MyClass);
         3. 变量名,方法名,成员名首字母小写(eg:name,value,targetObject);
         4. 单例对象遵循类的命名方式(eg:GlobalController);
         5. 常量全部大写,下划线分割单词(eg:APPLICATION_ID);

    参考:http://java.sun.com/docs/codeconv/

    * 变量所用单词尽量不用缩写。

    缩写的单词容易造成语意的不明,不易阅读,而且容易造成争议。

编码约定


    * 不要随意扩展原始对象。

    自Prototype 起,扩展原始对象似乎成了一个时髦的东西,大家都喜欢用。我承认他的便捷,但是请不要滥用,尽量做到有标准可循(比如为IE5扩展 Array.prototype.push),原始对象就这么几个,万一那天碰到两个人写的代码,行为不一致,那麻烦就大了。

    * 不要扩展Object.prototype。

    这个地雷貌似已经被头大牛踩到,但是你不要踩,谁踩到他,你就和他割席断交吧。

    * 不要盯上对象的constructor属性。

    constructor属性是非常不可靠的,很容易也经常被改写,而且经常被改写到Object对象[MyClass.prototype = {...}],能后你以为是你的构造器,动之,能后天下大乱。

    * 不要写那些中看不中用的集合。


    不要模仿Java 集合API,去写什么 HashMap,ArrayList。JavaScript不相信这些,这个世界简单才是硬道理。

    * 在结构中始终使用区块。

    莫偷懒,省略区块(即{ })会引发不经意的错误和麻烦。即使只有一句,也老老实实写上:

    * 单例模式直接使用对象申明。

    我们不需要那个不中用的构造函数, 不如直接来个对象申明,直接定义属性。

    * 变量名就是最好的文档。

    不要担心变量名称的长度,他们只是一个符号,符号的意义在于表明变量的意义,而大小的事就交给压缩工具吧。比如,可以使用thisPackage,targetPackage;而不要用pkg1,pkg2。

    * 表达式中赋值需要明确注释。

    直接在表达式中赋值可以使代码紧凑,但会降低程序可读性,应尽量避免,但是对于一些关键元素,可以采用(压缩/优化考虑),但必须明确注释。

    * 目录名以"/"结尾。

    JSI内核中,有一些地方需要记录目录地址。这里我们统一以“/”结尾。

    * 不要使用原始类型的对象量。

    原始对象有些诡异的地方,如。

      new String("test") != new String("test");
      if(new Boolean(false)){
        alert("执行到")
      }else{
        alert("未被执行")
      }

    对外接口可以考虑兼容,但是内部元素,不考虑,内部也不要使用这些对象。

    * 杜绝变量悬空现象

    不要出现:

    if (!window.Element){
        var Element = new Object();
    }

    改成:

    var Element = window.Element || new Object();


    这段代码来自大名鼎鼎的Prototype,这里没错,但是如果被拷贝到某个函数内,问题就大了,有此类问题的脚本,放在JSI中装载,也会存在问题。


一些诡异的技巧


    * {}就是Map

    哪简单对象当map是个非常方便的地方,缺点是key都被转化成string。但是大多数情况下还是够用的,简单就好,没必要复杂化。

    * []用作LinkedHashMap

    使用数组保存键的顺序,对象存储键的值,基本可以等价于LinkedHashMap结构。缺点是有上,同时,length不能为键。

    * 使用constructor == String代替typeof


    上面说到constructor不可靠,是的,但是constructor用来代替typeof,一般来说更可靠了。还可以同时做好对象类型和值类型的兼容。

    * 巧用与或。


      if(fn){

        fn();

      }

      -->

      fn&&fn();


慎用动态元素


    * eval

    eval的性能问题到不是主要的,主要理由依然是他的动态性,容易给程序带来不稳定因素。

    * with


    少用with,主要不是他的性能问题,其实with的性能问题并不太明显,但是他容易给程序带来不稳定因素。

    * execScript

    类似eval,ie上通行,不同之处在于他是一个上下文无关的eval,传入的脚本直接在全局上下文执行。

    * document.write

    当打印一段脚本标签时,近似等价与execScript

    * new Function

    不仅是动态元素,他同时还有一个上下文短路问题。

    * 少用属性。

    属性虽然是面向对象的常用元素,但JavaScript?属性的动态性太强,不便自动优化处理;同时属性的使用,将产生更多不稳定的状态,虽然貌似易于阅 读,却增加了程序的复杂性。实际编码中应该谨慎。常量性质的私有属性不要出现,能用变量的地方也不要随意升级为属性。

    * window.xyz

    有些人习惯用这个来申明全局变量,或者干脆不申明, 那么,改掉你的坏习惯。

评论
hotoo 2008-05-10
1. new String(”test”) != new String(”test”);
两次new String()得到两个(不同的)对象,内存地址当然不相同。

2. if(new Boolean(false)){
alert(”执行到”)
}else{
alert(”未被执行”)
}
new Boolean()得到的也是对象,在if里相当于true,当然“执行到”,你可以试一下: if(new Boolean(false).valueOf())
csf178 2008-05-02
每种语言都有自己的访问控制方式

既然javascript没提供scope对象以外的私有方式 还非要用不是很奇怪吗?
jindw 2008-05-02
hax 写道
我建议还是应该用单下划线表示 非public的 property/method。当然closure里的local var不必用下划线。但是如果是对象上的prop/method,则需要区分是否public。Python的习惯似乎也是一样的。


赞成这个观点。
在私有属性上,使用_前缀。

关于私有方法,我已经养成了另外一个习惯,那就是使用内部方法(全局元素的形式,但不在包定义文件中注册)。
也不单是方法,一切常量性质的私有属性都可以使用内部元素的方法做到真正的私有。
单是如果这个私有元素是个实例的变量,那就不适用了。
hax 2008-05-02
我建议还是应该用单下划线表示 非public的 property/method。当然closure里的local var不必用下划线。但是如果是对象上的prop/method,则需要区分是否public。Python的习惯似乎也是一样的。
jindw 2008-05-01
关于私有元素的命名约定,我偏向于不要下划线,下划线书写起来就不方便,看起来也比较难看,和减号太像,损人眼睛,就让他和普通元素一样,关于区别,交给ide去处理。

我记得eclipse源码最初都是用下划线做私有成员的前最,后来他支持对私有对象的不同着色,那个约定也就随之取消了。

当然这个故事,不一定在js ide上重演,只是,我个人已经养成了这个习惯了,不用下划线。

我们更关心的是最终公开元素的结构,私有的东西,个人愿意怎么干都行吧。
csf178 2008-05-01
trydofor 写道
补充一点,因为js变量没有作用域,所以可以参考pythone的标记方法
_var_
__var__
虽然比较难看,但是能够分清变量的作用域,避免泄漏

js作用域是通过closure控制是没问题的 私有完全可以做到

这种用奇怪名字避免重名的办法千万不要约定 约定的就容易冲突
自己可以规定一下
比如 喜欢钱的可以用这种 $_$var
trydofor 2008-05-01
补充一点,因为js变量没有作用域,所以可以参考pythone的标记方法
_var_
__var__
虽然比较难看,但是能够分清变量的作用域,避免泄漏
tommychang 2008-05-01
jindw 写道


* 杜绝变量悬空现象




不要出现:



if (!window.Element){

var Element = new Object();

}

改成:


var Element = window.Element || new Object();



这段代码来自大名鼎鼎的Prototype,这里没错,但是如果被拷贝到某个函数内,问题就大了,有此类问题的脚本,放在JSI中装载,也会存在问题。



我觉得都非常不错,但这个我觉得用逻辑运算符并没有用if那么明了,当然我觉得上面的代码或许改为:

var Element = window.Element;

if (!Element){

Element = new Object();

}

还有一点,不知道应不应该定义一下私有变量和函数的命名规则,比如用 __temp 或者 __temp__ 来命名呢?
csf178 2008-04-30
s79 写道
以上是IE5.5/IE6/IE7会出现的情况,在FF2/Opera9/Safari3里,除了var t="test",delete window.t返回false外,都返回true。
听说出IE8了还没试啥样呢。

忘标注了 这个测试结果是ie8的ie7模式的结果
jindw 2008-04-30
原来delete还有如此多的说法

我最初犯的一个错误式,误以为delete式删除变量的,后来发现,delete只是用来删除属性,纠正下来以为万事大吉了,没想到还有这样没完没了,呵呵

谢谢各位的精彩补充
s79 2008-04-30
以上是IE5.5/IE6/IE7会出现的情况,在FF2/Opera9/Safari3里,除了var t="test",delete window.t返回false外,都返回true。
听说出IE8了还没试啥样呢。
csf178 2008-04-30
  delete  t delete window.t
t="test" 成功 Exception
var t="test" 无效 Exception
window.t="test" Exception Exception

 

tmd 刚才没测 t="test" - -!

s79 2008-04-30
哦,惭愧,刚才没测试window.test
var test="test";alert(delete test);//false
test="test";alert(delete test);//true
test="test";alert(delete window.test);//IE出错
window.test="test";alert(delete test);//IE出错
window.test="test";alert(delete window.test);//IE出错
看来IE对var、无var、window.的处理是分三种……
hax 2008-04-30
s79 写道
hax兄,能吧。我刚还测试来的。
IE5.5/IE6/IE7/FF2/Opera9/Safari3都测了。公司要求这六种浏览器……


把这个代码贴到地址栏里测试吧:

javascript:try{alert(delete window.xyz)}catch(e){alert(e)}
csf178 2008-04-30
hax 写道
csf178 写道
事实上 delete window.xyz什么都做不了 哪种都没法删掉

有些时候window.xyz用来动态声明全局变量 不过有JSI的话当然就不需要了


delete window.xyz 是可以删掉的。问题是IE删不掉。因为在IE中window对象和所有DOM对象一样,无法用delete。

yes 就是指IE
hax 2008-04-30
s79 写道

关于delete大家可以做个测试。

以下代码写在最外层,不要写在函数里,我们看看var的作用。


请看此帖:http://www.javaeye.com/post/485956
s79 2008-04-30
hax兄,能吧。我刚还测试来的。
IE5.5/IE6/IE7/FF2/Opera9/Safari3都测了。公司要求这六种浏览器……
hax 2008-04-30
csf178 写道
事实上 delete window.xyz什么都做不了 哪种都没法删掉

有些时候window.xyz用来动态声明全局变量 不过有JSI的话当然就不需要了


delete window.xyz 是可以删掉的。问题是IE删不掉。因为在IE中window对象和所有DOM对象一样,无法用delete。
s79 2008-04-30

关于delete大家可以做个测试。

以下代码写在<script>最外层,不要写在函数里,我们看看var的作用。

var test="test";
alert(delete test);

 显示"false"。

test="test";
alert(delete test);//delete window.test也一样。

 显示"true",test不存在了。

window.test="test";
alert(delete test);//delete window.test也一样。

 同上。

所以说使用var声明的是一个变量,不能用delete对其操作。但可以用window.test访问之,也可以省略window直接访问。

不使用var,其实是给window添加了一个属性,自然也可以用window.test访问之,也可以省略window直接访问。也可以用delete删除之。

jindw 2008-04-30
s79 写道

"在结构中始终使用区块",如果if、for的{}里真的只有一句,不妨省略并与if、for写在一行。这和下边的巧用||、&&一样紧凑易读。

虽然我依然坚持我自己的风格,但是,我觉得,你的提法也可以接受。
但是,换行的写法,我坚决反对,那样太伤眼睛^_^


s79 写道

"少用属性",我觉得属性和方法一定是public的,可以供程序中其他模块或最终用户直接使用。不想公开属性或方法的就利用变量作用域做闭包,成为私有变量。

同意这个观点。那种下划线前缀的伪私有约定,其实并不怎么漂亮^_^
不过在JSI下,闭包就不必自己显式申明了。


s79 写道

"window.xyz"申明全局变量,和var xyz申明的全局变量不一样,var xyz申明的全局变量是不能用delete window.xyz删除的。一般调试程序的时候可以使用window.xyz来保存某个对象以便跟踪查看。

反对这种变量申明方式,因为,这个动态性太强,不便于自动工具处理与解析。当能, 在框架级别上还是可以考虑的,比如JSI导入的最后环节其实就是利用了这点。
发表评论

提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则

您还没有登录,请登录后发表评论

jindw
  • 浏览: 203643 次
  • 性别: Icon_minigender_1
  • 来自: 初到北京
  • 详细资料
搜索本博客
存档
最新评论