java基础:javascript面向对象的支持(1)

来源:互联网 发布:网络ssid是什么意思 编辑:程序博客网 时间:2024/05/21 17:30

1. javascript中的类型
--------
虽然javascript是一个基于对象的语言,但对象(object)在javascript中不是第一型的。js是以函数(function)为第一型的语言。这样说,不但是因为js中的函数具有高级语言中的函数的各种特性,而且也因为在js中,object也是由函数来实现的。??关于这一点,可以在后文中“构造与析构”部分看到更进一步的说明。

js中是弱类型的,他的内置类型简单而且清晰:
---------------------------------------------------------
undefined : 未定义
number    : 数字
boolean   : 布尔值
string    : 字符串
function  : 函数
object    : 对象


 1). undefined类型
========================
在ie5及以下版本中,除了直接赋值和typeof()之外,其它任何对undefined的操作都将导致异常。如果需要知道一个变量是否是undefined,只能采用typeof()的方法:


但是在ie5.5及以上版本中,undefined是一个已实现的系统保留字。因此可以用undefined来比较和运算。检测一个值是否是undefined的更简单方法可以是:


因此为了使得核心代码能(部分地)兼容ie5及早期版本,romo核心单元中有一行代码用来
“声明”一个undefined值:
//---------------------------------------------------------
// code from qomolangma, in jsenhance.js
//---------------------------------------------------------
var undefined = void null;

这一行代码还有一点是需要说明的,就是void语句的应用。void表明“执行其后的语句,且忽略返回值”。因此在void之后可以出现能被执行的任何“单个”语句。而执行的结果就是undefined。当然,如果你愿意,你也可以用下面的代码之一“定义undefined”。
//---------------------------------------------------------
// 1. 较复杂的方法,利用一个匿名的空函数执行的返回
//---------------------------------------------------------
var undefined = function(){}();

//---------------------------------------------------------
// 2. 代码更简洁,但不易懂的方法
//---------------------------------------------------------
var undefined = void 0;

void也能像函数一样使用,因此void(0)也是合法的。有些时候,一些复杂的语句可能不能
使用void的关键字形式,而必须要使用void的函数形式。例如:
//---------------------------------------------------------
// 必须使用void()形式的复杂表达式
//---------------------------------------------------------
void(i=1);       // 或如下语句:
void(i=1, i++);


 2). number类型
========================
javascript中总是处理浮点数,因此它没有象delphi中的maxint这样的常量,反而是有这
样两个常值定义:
  number.max_value  : 返回 jscript 能表达的最大的数。约等于 1.79e+308。
  number.min_value  : 返回 jscript 最接近0的数。约等于 2.22e-308。

因为没有整型的缘故,因此在一些关于css和dom属性的运算中,如果你期望取值为整数2,
你可能会得到字符串“2.0”??或者类似于此的一些情况。这种情况下,你可能需要用
到全局对象(gobal)的parseint()方法。

全局对象(gobal)中还有两个属性与number类型的运算有关:
  nan      : 算术表达式的运算结果不是数字,则返回nan值。
  infinity : 比max_value更大的数。

如果一个值是nan,那么他可以通过全局对象(gobal)的isnan()方法来检测。然而两个nan
值之间不是互等的。如下例:
//---------------------------------------------------------
// nan的运算与检测
//---------------------------------------------------------
var
  v1 = 10 * 'a';
  v2 = 10 * 'a';
document.writeln(isnan(v1));
document.writeln(isnan(v2));
document.writeln(v1 == v2);

全局对象(gobal)的infinity表示比最大的数 (number.max_value) 更大的值。在js中,
它在数学运算时的价值与正无穷是一样的。??在一些实用技巧中,它也可以用来做一
个数组序列的边界检测。

infinity在number对象中被定义为positive_infinity。此外,负无穷也在number中被定
义:
  number.positive_infinity  : 比最大正数(number.max_value)更大的值。正无穷。
  number.negative_infinity  : 比最小负数(-number.max_value)更小的值。负无穷。

与nan不同的是,两个infinity(或-infinity)之间是互等的。如下例:
//---------------------------------------------------------
// infinity的运算与检测
//---------------------------------------------------------
var
  v1 = number.max_value * 2;
  v2 = number.max_value * 3;
document.writeln(v1);
document.writeln(v2);
document.writeln(v1 == v2);

在global中其它与number类型相关的方法有:
 isfinite()   : 如果值是nan/正无穷/负无穷,返回false,否则返回true。
 parsefloat() : 从字符串(的前缀部分)取一个浮点数。不成功则返回nan。


 3). boolean类型
========================
 (略)

 4). string类型
========================
javascript中的string类型原本没有什么特殊的,但是javascript为了适应“浏览器实现的超文本环境”,因此它具有一些奇怪的方法。例如:
  link() : 把一个有href属性的超链接标签放在string对象中的文本两端。
  big()  : 把一对标签放在string对象中的文本两端。
以下方法与此类同:
  anchor()
  blink()
  bold()
  fixed()
  fontcolor()
  fontsize()
  italics()
  small()
  strike()
  sub()
  sup()

除此之外,string的主要复杂性来自于在javascript中无所不在的tostring()方法。这也是javascript为浏览器环境而提供的一个很重要的方法。例如我们声明一个对象,但是要用document.writeln()来输出它,在ie中会显示什么呢?

下例说明这个问题:
//---------------------------------------------------------
// tostring()的应用
//---------------------------------------------------------
var
  s = new object();

s.v1 = 'hi,';
s.v2 = 'test!';
document.writeln(s);
document.writeln(s.tostring());

s.tostring = function() {
  return s.v1 + s.v2;
}
document.writeln(s);

在这个例子中,我们看到,当一个对象没有重新声明(覆盖)自己tostring()方法的时候,那么它作为字符串型态使用时(例如被writeln),就会调用java script环境缺省的tostring()。反过来,你也可以重新定义javascript理解这个对象的方法。

很多javascript框架,在实现“模板”机制的时候,就利用了这个特性。例如他们用这样定义一个fontelement对象:
//---------------------------------------------------------
// 利用tostring()实现模板机制的简单原理
//---------------------------------------------------------
function fontelement(innerhtml) {
  this.face = '宋体';
  this.color = 'red';
  // more...

  var ctx = innerhtml;
  this.tostring = function() {
    return ''
      + ctx
      + '';
  }
}

var obj = new fontelement('这是一个测试。');

// 留意下面这行代码的写法
document.writeln(obj);


 5). function类型
========================
javascript函数具有很多特性,除了面向对象的部分之外(这在后面讲述),它自已的一些独特特性应用也很广泛。

首先javascript中的每个函数,在调用过程中可以执有一个arguments对象。这个对象是由脚本解释环境创建的,你没有别的方法来自己创建一个arguments对象。

arguments可以看成一个数组:它有length属性,并可以通过arguments[n]的方式来访问每一个参数。然而它最重要的,却是可以通过 callee 属性来得到正在执行的函数对象的引用。

接下的问题变得很有趣:function对象有一个 caller 属性,指向正在调用当前函数的父函数对象的引用。

??我们已经看到,我们可以在javascript里面,通过callee/caller来遍历执行期的调用栈。由于arguments事实上也是function的一个属性,因此我们事实上也能遍历执行期调用栈上的每一个函数的参数。下面的代码是一个简单的示例:

//---------------------------------------------------------
// 调用栈的遍历
//---------------------------------------------------------
function foo1(v1, v2) {
  foo2(v1 * 100);
}

function foo2(v1) {
  foo3(v1 * 200);
}

function foo3(v1) {
  var foo = arguments.callee;
  while (foo && (foo != window)) {
    document.writeln('调用参数:
', '---------------
');

    var args = foo.arguments, argn = args.length;
    for (var i=0; i      document.writeln('args[', i, ']: ', args[i], '
');
    }
    document.writeln('
');

    // 上一级
    foo = foo.caller;
  }
}

// 运行测试
foo1(1, 2);
         (责任编辑:包春林)