2009年05月02日

Javascript:element の判定とそれに関わる諸事

nodeType 調べるだけでは問題がある場合の element の判定方法です。

・ chrome での動作の相違
・ prototype.js では Element が使えない

以前も似たようなものをUPしたのですが、2年も!放置していたので、今使っているものを紹介。
Javascript:DOMオブジェクトかECMAオブジェクトかを判定する。
こちらで Element を使えば良いというお話しが出ているのですが、実は Element では prototype.js など使わざる得ない場合(他の人が作成したものの改造とか・・・)に期待どおり動きません。
しかも prototype.js の利用率って意外と馬鹿にならない。

■ 確認環境
ie 5.0, 6.0, 7.0, 8.0
ff 1.0, 1.5, 2.0, 3.0
op 7.02, 8.53, 9.01
ns 6.2, 7.1
safari 4.0beta(for win)
sleipnir 2.3
google chrome

各 prototype.js あるなしです。ちなみに ie5.0 は prototype.js 動きません。
最新が無いものも目立ちますが op とかw





 ソース


function isElement(e){
  var r = null;
  if(e && e.nodeType === 1){
      try{
        r = e.cloneNode(false);
      }catch(n){
        return false;
      }
      try{
        if(r == e){
          return false;
        }else{
          // CloneNode で別物なら書換え試行
          r.nodeType = 9;
        }
        if(r.nodeType === 1){
          // Cr は error にならないが書き換えられない。
          return true;
        }else{
          return false;
        }
      }catch(n){
        // Cr 以外は error になる
        return true;
      }
  }else{
    return false;
  }
}


hasOwnProperty すら使っていません。
実は、cr ですと hasOwnProperty で nodeType を見ると true になってしまう。

確認例)
var ele = document.createElement('div');
alert(ele.hasOwnProperty('nodeType'));


ff ですと当然 false ですし、ie では [element] に hasOwnProperty はありません。

また、[element].nodeType に値を入れようとすると多くのブラウザでは、例外が発生するのに対し、cr では無言?です。
ただし、書き換えられない

結局、prototype.js のようなライブラリを使う場合、hasOwnProperty の動作がブラウザ毎に異なることや、Element や Object など簡単に書き換えられるという事を加味すると、動作上許されないようなメソッドやプロパティを利用するしか手が無い訳です。
つまりここで使用しているのは cloneNode と nodeType への書き込み。

cloneNode で自身を返すような、イヤらしい自前のオブジェクトはそのまま false になりますし、ちゃんと別物を返すような場合は、実際 nodeType を書き換えてやっても問題ない訳です。

通常 nodeType 調べれば事足ります。
苦労してアップしつつ骨折りな事追記してますがw
cloneNode や例外を投げるような事をしていますので、当然余分に負荷が掛かります。
ごちゃごちゃと得体の知れない事をしているスクリプトには、無用な誤動作を防止できると思います。ま、それでも nodeType 持っているオブジェクト+protoype.jsってところでしょうけど。

※ これぐらいのものでも正答します。
function mimic(){}
mimic.prototype.nodeType = 1;
mimic.prototype.hasOwnProperty = function (p){
  // ちなみにこれは完ぺきではない
  return (this[p] && !this.constructor.prototype[p]);
};
mimic.prototype.cloneNode = function (){
  return this;
  // とか
  return {};
}


※ こんなイジワルされると誤答しますw
mimic.prototype.cloneNode = function (){
  return document.createElement('div');
}



posted by HiFa at 15:38 | 🌁 | Comment(0) | TrackBack(0) | JavaScript雑感 | このブログの読者になる | 更新情報をチェックする
>>> スパムコメントは消してますよん。 お互い無駄な労力は避けましょう。 <<<

この記事へのコメント

コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/118457190
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。