skip to main |skip to sidebar

2007-11-03

ECMAScript4 草案的新标准解读

概要

ECMAScript4的新标准可以分为

  • 从 ActionScript 3.0 继承的新标准
  • 从 JavaScript1.7 继承的新标准
  • 其他的新标准

从 ActionScript 3.0 继承的新标准

与OOP和类型相关的标准与ActionScript 3.0几乎一样。

  • class,interface
  • 属性,const
  • 继承
  • 命名空间,package
  • int,double类型
  • ...args
  • is,as运算符
  • try-catch的类型匹配
  • 末尾的逗号(Trailing commas),比如{a : 10,}

从 JavaScript1.7 继承的新标准

  • 作用域(let)
  • 多值代入([a, b] = [1, 2])
  • 迭代(Iterator)
  • yield
  • 数组闭包

FireFox 2使用的是 JavaScript 1.7。

其他的新标准

重载函数(generic functions)

使用Overload可能更恰当。

generic function intersect(s1, s2); // No body here

generic function intersect(s1: Shape, s2: Shape) {
    // general intersection method 
}

generic function intersect(s1: Rect, s2: Rect) {
    // fast intersection for rectangles 
}

模板类 (parameterized class)

类似于 Java 5.0 新添加的Generics。可以避免运行时的类型检查,提高运行速度。

class Pair.<T> {
var first: T, second: T;
}

new Pair.<int>(3, 4);
type Box.<T> = {
 value: T
}
var v: Box.<boolean> = new Box.<boolean>(true);

function f.<T>( x:T ): T {
    //Do sth...
}

f.<int>(37)

Vector与Map

Vector为Array的严密版;Map为使用Object的HashTable,相当于 ActionScript3.0 的 Dictionary类的严密版。它们都支持迭代与模板。并且在编译时做了类型检查,所以速度很快。

var xs = new Vector.<double>;
var map = new Map.<*,int>;

记录与数组类型(Record and array types)

记录类型(Record type)就像{x:int, y:string}的样子,好像受了Scheme等函数型语言的影响。Object的模板?

var samplevar = new { x:int, y:string }( 3, "foo" );
var samplevar = { x:10, y:"foo" } : { x:int, y:string }; 

但是属性可以进行添加与删除,也就是说并非制定严密的类型。如果想严密,必须定义Class!

就我看来,这种语法不大好,有点罗嗦。我认为以下似乎更好:

var samplevar = new {x:int = 3, y:String = "foo"};

数组类型使用[int]的方式来定义。

var intarray = new [int](7);
var intarray = [1, 2, 3]:[int];

以上两种类型均可以与新添加的关键字 likewarp 组合起来使用。

function func1( pt: like { x: int, y: int } ) {...}
function func2( pt: * ) {
     if( pt is like {x : int, y : int} ) { ... }
}
function func3( pt: wrap { x: int, y: int } ) {...}

有趣的是使用 like 可以匹配特定种类的class,而不必非要在继承树下面的。比如ActionScript3.0的 PointSprite 的超类虽然不一样(除 Object 以外),但都有xy属性。使用记录类型的话,就可以匹配以上两种类型,增加了柔软性。

每次都写 { x:int, y:int } 太麻烦了,多次使用时可以使用新的关键字 type 来定义。

type Position = { x:Number, y:Number };

其他,数组类型与变长参数可以一起使用。

function (int, ...[string]): void {...}

运算符的重载(Operator overloading)

运算符均为全局函数,在 intrinsic 的命名空间里面定义。

class Complex {...}
generic intrinsic function +( a: Complex, b: Complex ) {
     new Complex( a.real + b.real, a.imag + b.imag )
}
generic intrinsic function +( a: Complex, b: Number ) {
     a + Complex(b)
}
generic intrinsic function +( a: Number, b: Complex ) {
     Complex(a) + b;
}

禁止null值(Nullability)

在类型后面添加!来禁止null值的代入。

var v:C! = ...
function (v:Object!) {...}
class Complex! {...}

末尾调用(Tail calls)

在函数的末尾调用函数或返回调用函数的值时,不进行压栈、调用,而直接使用 goto 来编译。特别在递归调用时,调用过程变为了循环,对速度有显著的提高。

元层次挂钩(Meta-level hooks)

管理函数的调用,值的代入等,可以使用meta::invokemeta::getmeta::setmeta::hasmeta::delete。类似于 ActionScript 3.0 的 Proxy,只能在动态类里使用。

Array与Vector也使用了Meta-level hooks。在之前无法自己写Arra(因为无法同时继承 ArrayProxy),但通过使用Meta-level hooks,这一切将成为历史。

结合类型(Union type)

创建可以匹配多个类型的类型比如 (int,String) 可以匹配 intString 类型。

type AnyNumber = (byte,int,uint,double,decimal,Number);//匹配任何数字的类型

特别地,常量 any 等于 (null,undefined,Object),可以匹配任何类型。

选择类型(switch type)

以前,switch只匹配较值,需要匹配类型时只能使用 if(v is String){...}else if(v is Number) {...}... 但现在可以使用switch type。

switch type (v) {
    case (s:string) { ... }
    case (d:Date) { ... }
}

截取(Slicing)

截取子集,可以在 StringArrayVector 里使用。

"ecmascript"[5:2:-1]// => "sam"

正则表现(Regular Expressions)的多行与注释

正则表现支持多行与以#开头的注释。复杂的正则表现的阅读性大大提高!

/# The protocol is an alpha name followed by colon and double slash
 (?P<protocol> [a-z]+)
 :
 \/\/
 # The host is two or more dot-separated alpha names
 (?P<host> [a-z]+ (?: \. [a-z]+ )+)
 # The path is optionally present
 (?P<path> (?: \/ [a-z]+ )* \/? )
/x

支持JSON

toJSONStringString.parseJSON

还有很多新标准,详细请看 Proposed ECMAScript 4th Edition – Language Overview

没有评论: