• JScript and DOM changes in IE9 preview 3


    3rd preview of IE9 was released yesterday, with some amazing additions, like canvas element and an extensive ES5 support. I’ve been digging through it a little, to see what has changed and what hasn’t — mainly looking at JScript and DOM. I posted some of the findings on twitter, but want to also list them here, as it’s not very convenient to share code snippets in 140 characters. Referencing it all in one place will hopefully make it easier for IE team to find and fix these deficiencies.

    ECMAScript 5 and JScript

    The big news is that IE9pre3 has (almost) full support for ES5. By “full support”, I mean that it implements majority of new API, such as Object.create, Object.defineProperty, String.prototype.trim, Array.isArray, Date.now, and many other additions. As of now, IE9 implements the largest number of new methods; even more than latest Chrome, Safari and Firefox. Unbelievable, isn’t it? :)

    screenshot of es5 compatibility table

    You can see the results in this compatibility table (note that it lists results of mere “existence” testing, not any kind of conformance).

    What’s missing is strict mode, which actually isn’t implemented in any of the browsers yet.

    Some of the things I noticed:

    ES5 Object.getPrototypeOf on host objects seems to lie, always returning null instead of proper value of [[Prototype]]:

      Object.getPrototypeOf(document.body); // null
      Object.getPrototypeOf(document); // null
      Object.getPrototypeOf(alert); // null
      Object.getPrototypeOf(document.childNodes); // null
    

    This doesn’t happen in other browsers that implement Object.create at the moment, such as latest Chrome, WebKit or Firefox. In Chrome, for example:

      Object.getPrototypeOf(document.body) === HTMLBodyElement.prototype;
      Object.getPrototypeOf(document) === HTMLDocument.prototype;
      Object.getPrototypeOf(alert) === Function.prototype;
      Object.getPrototypeOf(document.childNodes) === NodeList.prototype
    

    … and so on.

    Interestingly, bound functions in IE9pre3 are represented as “function(){ [native code] }”, similar to host objects:

      var bound = (function f(x, y){ return this; }).bind({ x: 1 });
      bound + ''; // "function(){ [native code] }"
     
      // compare to
     
      alert + ''; // "function alert(){ [native code] }"
    

    Note how function representation does not include identifier (f), parameters (x and y), nor representation of function body (return this;). This of course proves once again that relying on function decompilation is NOT a good idea.

    Whitespace character class (as in /\s/) still doesn’t match majority of whitespace characters (as defined by specs). These include “U+00A0”, “U+2000” to “U+200A”, “U+3000”, etc. The test is available here. Curiously, ES5 String.prototype.trim seems to “understand” those characters as whitespace very well, producing empty string — as expected — for something like '\u00A0'.trim().

    It was nice to see that ES5 Array.isArray is about 20 times faster than custom implementation, such as this one:

      function isArray(o) {
        return Object.prototype.toString.call(o) === "[object Array]";
      }
    

    The difference in speed is similar to other browsers that implement this method.

    An infamous, 10+ year-old JScript NFE bug, which I described at length before, is finally fixed:

      var f = function g() { return f === g; };
      typeof g; // "undefined"
     
      f(); // true
    

    arguments’ [[Class]] is now an “Arguments”, just like ES5 specifies it:

      var args = (function(){ return arguments; })();
      Object.prototype.toString.call(args); // "[object Arguments]"
    

    DOM

    Unfortunately, the entire host objects infrastructure still looks very similar to the one from IE8. Host objects don’t inherit from Object.prototype, don’t report proper typeof, and don’t even have basic properties like “length” or “prototype”, which all function objects must have:

      
     alert instanceof Object; // false
      typeof alert; // "object"
      alert.length; // undefined
    

    Because they don’t inherit from Object.prototype, we don’t have any of Object.prototype methods, naturally:

      
     alert.toString; // undefined
      alert.constructor; // undefined
      alert.hasOwnProperty; undefined
    

    Object.prototype is not the only object host methods fail to inherit from. In majority of modern browsers, host objects also inherit from Function.prototype and so have Function.prototype methods like call and apply. This doesn’t happen in IE9pre3.

      
      alert instanceof Function; // false
      document.createElement instanceof Function; // false
      alert.call; // undefined
    

    Curiously, call and apply are present on some host objects, but they are still not inherited from Function.prototype:

      
      typeof document.createElement.call; // "function"
      document.createElement.call === Function.prototype.call; // false
     

    Host objects’ [[Class]] is far from ideal as well. IE9pre3 actually violates ES5, which says that objects implementing [[Call]] (or in other words — are callable) should have [[Class]] of “Function” — even if they are host objects. In IE9pre3, alert is a callable host object, yet it reports its [[Class]] as “Object” not “Function”. Not good.

      
      Object.prototype.toString.call(alert); // "[object Object]"
      Object.prototype.toString.call(document.createElement); // "[object Object]"
      

    IE9pre3 still messes up DOM objects’ attributes and properties, although not as badly as earlier versions:

      
      var el = document.createElement('p');
      el.setAttribute('x', 'y');
      el.x; // 'y'
     
      el.foobarbaz = 'moo';
      el.hasAttribute('foobarbaz'); // true
      el.getAttribute('foobarbaz'); // 'moo'
      

    Some old, humorous bugs can still be seen in IE9pre3, such as methods returning “string” when applied typeof on:

      
      typeof Option.create; // "string"
      typeof Image.create; // "string"
      typeof document.childNodes.item; // "string"
      

    Undeclared assignments still throw error when same-id’ed elements are present in DOM, however not with same-name’ed elements (as it was in previous versions):

      
      <div id="foo"></div>
      <a name="bar"></a>
      ...
      <script>
        foo = function(){ /* ... */ }; // Error
        bar = function(){ /* ... */ }; // no Error
      </script>
     

    Similarly to IE8, only Element and specific element type interfaces (HTMLDivElement, HTMLScriptElement, HTMLSpanElement, etc.) are exposed as same-named global properties. Node and HTMLElement are still missing, and element’s prototype chain most likely still looks like this:

      
      document.createElement('div');
        |
        | [[Prototype]]
        v
      HTMLDivElement.prototype
        |
        | [[Prototype]]
        v
      Element.prototype
        |
        | [[Prototype]]
        v
      null
     

    …rather than what can be seen in almost all other modern browsers:

      
    document.createElement('div');
        |
        | [[Prototype]]
        v
      HTMLDivElement.prototype
        |
        | [[Prototype]]
        v
      HTMLElement.prototype
        |
        | [[Prototype]]
        v
      Element.prototype
        |
        | [[Prototype]]
        v
      Node.prototype
        |
        | [[Prototype]]
        v
      Object.prototype
        |
        | [[Prototype]]
        v
      null
        v
     

    getComputedStyle from DOM Level 2 is still missing, however its value is mysteriously a null, not undefined. The property actually exists on an object, but has a value of null. Hopefully, this is just a placeholder and proper method will be added before final release.

      
      document.defaultView.getComputedStyle; // null
      'getComputedStyle' in document.defaultView; // true
     

    Array.prototype.slice can now convert certain host objects (e.g. NodeList’s) to arrays — something that majority of modern browsers have been able to do for quite a while:

      
      Array.prototype.slice.call(document.childNodes) instanceof Array; // true
     

    That’s it for now.

    Unfortunately, I don’t have much time to look into these things extensively, at the moment. There might be more updates on twitter.

    As always, any corrections, suggestions, and additions are much appreciated.

  • 相关阅读:
    C#中get和set的写法
    FineUI中Newtonsoft.Json版本报错解决办法
    ExtAspNet和FineUI未将对象引用设置到对象的实例
    【转载】写runat="server"有什么用
    (object sender,EventArgs e)是什么?
    【转载】onclick与onCommand的区别
    简单总结------redis
    将list等分成n份
    将List 分成n个长度由调用者指定的子List
    CountDownLatch 我的应用场景
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1766430.html
Copyright © 2020-2023  润新知