百度首页 | 百度空间
 
查看文章
 
es4修正的一些bug
2007年11月07日 星期三 上午 00:57

Bug Fixes in JavaScript 2


As the the ECMAScript 4 (JavaScript 2) specification comes closer to its final form, a number of aspects have, already, congealed and able to be disseminated and learned. Specifically, the bug fixes to ECMAScript 3 that are being included in ECMAScript 4 are quite refined at this point.

The bug fixes to JavaScript came from a number of places. Generally, however, they have come about due to aspects being under-specified, causing confusion to occur amongst language implementors.

Additionally, bug fixes have come about from universal conventions that have been adopted by implementors causing them to be ported back into the specification.

A full list of the bug fixes can be found on the ECMAScript 4 wiki.

You’ll, generally, find that a number of these fixes are already included in some browser implementations (generally more-so in Spidermonkey-based ones, than others). However, a couple of these are implemented in no browser, at this point (like this propagation) and still others are implemented in all browsers (like single character substrings).

More than anything else, however, these changes represent an attempt to bring greater levels of common-use compatibility to the language (allowing more web pages to work) and bringing backwards compatibility inline with ECMAScript 3 implementations, rather than with the specification.

Generally, you should use this as a guide of what’s to come, not as of what you can universally use, right now.

arguments is now a ‘real array’

arguments is now a ‘real array’, as opposed to an array-like object, with the following distinctions:

  • arguments.toString() behaves like an object’s .toString(), rather than an array’s.
  • If you manipulate the .length property its contents aren’t deleted (if the length is reduced), nor are new items added (if the length is increased).

This means that you can now do simple things like:

arguments.slice(1);

Whereas, previously, you would have to do:

Array.prototype.slice.call( arguments, 1 );

typeof /regexp/ == 'object'

This change makes it such that callable objects return a typeof of ‘object’ rather than of ‘function’.

The result of this fix is best exhibited by an uncommon feature in Spidermonkey that’s caused a lot of confusion. Many don’t know this, but you can do this with a regular expression (in Firefox, et. al.):

/test/('test')
// is equivalent to:
/test/.exec('test')

In this case, a regular expression is an object that is also callable (thus the typeof was actually ‘function’ rather than ‘object’). So while fixing typeof of a RegExp, in Spidermonkey, isn’t a true ECMScript 4 bug fix, it’s indicative of the larger problem being solved. In reality, most users expect the typeof value to be ‘object’ in this case. The adjustment is that callable non-functions now have a typeof of ‘object’, allowing this to behave as one would expect:

typeof /regexp/ == 'object'

this propagation

If you now define a function inside another, its this is bound to the this of the outer function, as opposed to the global object (e.g. window).

This makes the following code possible:

function User(name){
  this.name = name;
 
  function test(){
    alert(this.name);
  }
 
  test();
}

Whereas, previously, you would’ve had to have used a closure to store a reference to this and retrieve it within test(). The resulting code would have looked something like this:

function User(name){
   var self = this;
   this.name = name;
 
   function test(){
     alert(self.name);
   }
 
   test();
}

undefined, NaN and Infinity

undefined, NaN and Infinity are now immutable global properties. Some implementations already took some of these into account, but now it’s being standardized.

Thus you can do:

1/0 == Infinity
1/'foo' == NaN

RegExp Reconstruction

/regexp/ creates a new, unique, object every time it’s evaluated. For example, the following evaluated to true, previously, even though it shouldn’t have:

var test = [];
for ( var i = 0; i < 2; i++ )
 test.push( /test/ );
test[0] == test[1]
>> true

This now brings RegExp literals in line with all other literals (as to how they are evaluated). This bug led a number of people astray - and in the end it was the third most duplicated JavaScript bugs.

Trailing Commas

When initialising an object, trailing commas are ignored (some implementations already support this).

var obj = {
 a: 1,
 b: 2,
};

It’s now being made expressly clear that a trailing comma in an array initialisation does not create an extra undefined entry at the end of the array. JScript currently gets this implementation detail wrong, even though it was specified in ECMAScript 3. The correct result is as follows:

[a, b,].length
>> 2 (not 3)

Single-Character Substrings

You can now get single characters out of a string by using [index], instead of the .charAt(index) method. This way was already widely implemented.

'string'[0]
>> 's'

Undefined Looping

You can now do a for .. in loop against an undefined object (or a null) without an exception being thrown. For example:

for ( var i in null ) {}
for ( var i in undefined ) {}

This was, originally, intended to throw an error in ECMAScript 3 but this has been reverted due to web pages coming to expect this to work.

Comparison Order

When performing a comparison of two items the order in which they were compared was not guaranteed. It is now specified that the values be retrieved in left-to-right order.

For example, this is what could have happened previously:

var a = {
 valueOf: function(){
  alert('a');
  return 1;
 }
};
 
var b = {
 valueOf: function(){
  alert('b');
  return 1;
 }
};
 
a<b
>> alert('a')
>> alert('b')
>> false
 
a>b
>> alert('b')
>> alert('a')
>> false

for .. in order

When looping through the properties of an object the order in which they were returned was left up to the implementation - now it’s required that the properties be returned in the order in which they were created. The final result would allow for the following, intuitive, result:

var obj = {1: 2, p: 'hi', '_':'under'};
for ( var i in obj )
 alert(i);
>> alert('1')
>> alert('p')
>> alert('_')

Implementations since JavaScript 1 have generally done it this way (and implementations that haven’t have found that web pages generally require this convention). Thus, it’s being made expressly clear now that this is the case.

Posted: October 31st, 2007 · Tags: javascript2, ecmascript, mozilla, javascript

个人十分不喜欢内部声明function的调用this制向修正,因为这打破了js一个规律,就是函数调用,前面只要没有主语,就是对象,或者显式通过call apply指定对象,this默认是window的做法,可能会使内部函数默认对象this和外部函数默认window this导致问题更加复杂,反正closure也是必须的,觉得修正可能越修越乱

类别:javascript&web2.0 | 添加到搜藏 | 浏览() | 评论 (2)
 
最近读者:
 
网友评论:
1
2007年11月29日 星期四 上午 10:24
我倒认为 内部的function 应该能访问this(当前对象),不然每次都需要去出处理这个scope问题,在VC++,Java中这么庞大的oop语言都这么做,为什么es4不能去修正?
 
2
2007年11月29日 星期四 下午 02:07
当然不能修正,现在代码当中由于内部scope当中声明函数this指向host,所以都使用scope内部scope变量保存对象this,从而在function内部使用内部scope变量调用对象this,不排除很多代码使用this去获取window对象的很多可能性,改变了this,就改变了js的函数scope环境确认法则,当然会导致不兼容出现,所以这个东西决不能改变,好在现在es4实现还没有对这个改变,这个说大了,也可以在构造当中把内部声明function绑外面去,那this是谁,只能进一步混乱,所以还是不能改变
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码:
 

     

©2008 Baidu