论坛首页 Web前端技术论坛

JavaScript 的几个 tip

浏览 24561 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-07-08  
1、JavaScript 中的继承
在 JavaScript 中实现继承的方法是:将子类的 prototype 属性设置为父类的对象。
例如,我有一个 Basket 类,继承 Hashtable 类:
Basket.prototype = new Hashtable();;
Basket.prototype.constructor = Basket; 

如果不写上面第二句,以后 typeof 一个 Basket 的对象获得的就是 Hashtable 了。

但是需要注意的是,由于所有的子类(Basket)的对象实例共享同一个原型对象(Hashtable),因此在父类对象的构造函数中只能保存对所有子类对象均相同的实例变量。对每个子类不同的实例变量必须放在子类的的构造函数中。很多时候父类对象没有任何自己的实例变量,而只有一些方法,操作的是子类对象的实例变量。

2、JavaScript 中变量的作用域
var v = "aaa";
function func(); {
    alert(v);;
    ...
    var v = "bbb";
}

alert 出来的是什么?你肯定会说是 "aaa",错,alert 出来的是 "undefined"。为什么?
因为 JavaScript 为了简化处理,变量实际上只有两种作用域,全局变量和函数的内部变量。你在函数内部任何一个地方定义的变量其作用域都是整个函数体。而在 alert 的时候函数的内部变量 v 已经定义了,并且覆盖掉了同名的全局变量 的定义,只是还没有被初始化,所以 alert 出来的是 "undefined"。

3、undefined 和 null
有些开发人员误以为在 JavaScript 中,
return;
返回的就是 null,也就是
return null;

这是一个误解,在 JavaScript 中,
return;
返回的是 undefined,而不是 null。这两个值是有区别的,请看《JavaScritp 权威指南》的相关内容。最好明确地写为:
return null;

这个问题同样在传递参数时候也会出现,例如:
function func(v1, v2); { 
    alert(v2);; 
} 
func(1);; 

alert 显示 v2 的值是 undefined。

虽然在 JavaScript 中:
undefined == null;
得到的结果是 true,将一个 typeof 为 "undefined" 的标识符与 null 做等值比较结果也是 true,似乎这两个值可以混用。但是为了理解的清晰,最好还是把这两个值区分开。

还有一个需要注意的是在 SP2 以前版本的 IE5 中,不能直接拿 undefined 与其它值比较,例如:
if(v2 == undefined);  { 
    ... 
} 

在 SP3 以上版本的 IE5、IE6 都没问题,但是在 SP2 版本前的 IE5 中无法执行。必须要写成:
if(typeof v2 == "undefined");  { 
    ... 
} 
   发表时间:2004-07-08  
想起c2上看到的一些JavaScipt oddities and bugaboos,这里贴出来:
  Some JavaScipt? oddities and bugaboos:

Variable declarations are optional (much like BasicLanguage); though if you read an undeclared variable before writing to it you'll get an error. (Writing to an undeclared variable declares it - in the global scope)

Language is WeaklyTyped, and the automatic coercions that it does can produce surprising results. "2" + "3" is "23" (+, when applied to two strings, performs concatenation); "2" * "3" is 6. (Multiplication not defined for strings; so the language tries converting them to numerals, succeeds, and multiplies those). This can be surprising.

Rather annoying gotcha in array constructor. new Array() returns a newly created empty array; new Array(2,3) returns a newly-created array with 2 and 3 as its two elements. new Array(5) does not return a newly-created array with 5 as its single element; instead, it returns a 5-element array!

Whereas most languages have one universal singular value (null/nil/Void/whatever); JavaScript has two - "null" and "undefined". With somewhat interesting and irregular semantics.

No integral types - the only numeric type supported is an IEEE754 double-precision float. For a scripting language, this limitations is probably less obnoxious than it would be elsewhere.

Language has LexicalScoping, but with an interesting twist. Unlike JavaScripts brethen C/C++/Java/C#/etc, where variables introduced in an anonymous block within a function are only valid within that block; in JavaScript such variables are valid for the entire function. In other words:

if (a == b)
{
     var c = "Equal!";
}

if (c == "Equal!") {
     // do something
}


is legal JavaScript. If the first condition is not true, c will evaluate to "undefined".

Semicolons are optional in JavaScript; if the parser sees a line break it will try and interpret the two lines as separate statements (if it can't it then tries to interpret them as a single statement). This too can produce surprising results.
0 请登录后投票
   发表时间:2004-07-29  
4、当你为一个类添加一个方法时,你经常这样写:
ClassName.prototype.f1 = function (); {
    ...
}

你可能想当然地认为 f1 就是这个方法的名称。你想错了,f1 只是这个类的对象的一个普通属性而已,它的值可以是任何类型。这个方法是匿名的,在全局名字空间中并没有它的标识符。如果想在全局名字空间获得一个标识符,你应该采用如下两种方式:
function func1 (); {
    ...
}
ClassName.prototype.f1 = func1;

或者
ClassName.prototype.f1 = function func1 (); {
    ...
}

这样做的好处是你现在可以在多个类中重用相同的方法(可能性似乎很小,是吧?)。
我这里还是按照面向对象的习惯叫做方法。一般在 JS 中我把类中的 function 称做方法,而把全局范围的 function 称做函数。
0 请登录后投票
   发表时间:2004-07-29  
5、重载父类的方法后如何调用父类的方法?
你现在已经知道 JS 完全可以实现继承了,当然也可以实现重载,否则还能叫面向对象语言吗?比如在父类 BaseClass 中有一个 f1 的方法,子类 SubClass 要重载这个方法,只需要这样写:
SubClass.prototype.f1 = new function (); {
    ...
}

且慢,如果我还想调用父类的方法怎么办呢?不必担心,
SubClass.prototype.f1 = new function (); {
    BaseClass.prototype.f1.apply(this, arguments);;
    ...
}

这里加的一句就是调用父类的 f1 方法。apply 换成 call 也是可以的。
不过 JS 因为函数参数数量是可变的,所以它并不会把
function f1 (arg1, arg2, arg3)

function f1 ()
看做是两个函数,它会认为它们就是一个函数(小子,换了个马甲就以为我认不出你了?),后面出现的定义会覆盖前面的定义。所以即使你改变子类方法的签名,它仍然认为是重载了父类同名的方法。

那么如果我还想调用父类的构造函数怎么办呢?这样做:
function SubClass (arg1, arg2); {
    BaseClass.call(this, arg1, arg2);;
    ...
}
0 请登录后投票
   发表时间:2004-07-29  
6、JavaScript 开发如何做自动测试?
JavaScript 也是可以做自动测试的。xUnit 框架在 JS 领域的嫡系传人是 JsUnit(http://jsunit.berlios.de),基本上就是 JUnit 的 JS 版,连例子都是从 JUnit 的例子移植过来的。
如何用 TDD 方式做 JS 开发?这个话题可就大了,足够说上几天的,以后我会另开主题讨论这个问题。

待续...
0 请登录后投票
   发表时间:2004-07-30  
漂亮!伸个大拇指
0 请登录后投票
   发表时间:2004-07-30  
非常感谢楼主把js很多关键有用的语法总结在一起。

下面两个link也是我在调查"undefined"和null的时候找到的。
http://www2.cyut.edu.tw/~s9154610/jscript.html
http://tech.irt.org/articles/js169/

还看到一个可以模仿声明java package的Java Script项目。
http://sourceforge.net/projects/jspackaging/

关于“面向对象”JS编程(继承,多态,封装),如果有时间和兴趣,楼主能否多讲一些?多谢。
0 请登录后投票
   发表时间:2004-08-13  
http://sourceforge.net/projects/jsunit/

JsUnit的 下载地址
0 请登录后投票
   发表时间:2004-09-02  
7、为什么 type="file" 的 input 控件的 value 是只读的?
这次这个问题与 JS 本身没有多大关系。而是一个 Web 安全设计方面的问题。

我们来想想,假设这个 input 控件的 value 不是只读的会出现什么情况。

你上网冲浪的时候打开了一个页面,这个页面上有一个很好玩的 flash 游戏,你玩得非常开心。可是就在你愉快地玩游戏时在页面的背后静悄悄地发生了一些你所不愿意发生的事情。

在这个页面上有一个隐藏的 iframe,iframe 中有一个 form 表单,表单中有一个 type="file" 的 input 控件,有一段 JavaScript 或者 VBScript 代码把这个 input 控件的 value 设置成了你的机器上某个重要文件(比如,你是个懒人,从来不愿意记忆信用卡账号和密码,宁可把这些信息存在机器上的某个 txt 文件中)直接上传到了服务器。

现在那个服务器的管理员和你一样乐呢。而你就等着哭吧。
0 请登录后投票
   发表时间:2004-09-02  
dlee 写道
7、为什么 type="file" 的 input 控件的 value 是只读的?
这次这个问题与 JS 本身没有多大关系。而是一个 Web 安全设计方面的问题。


呵呵,多年疑惑,一朝而解。谢了!
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics