読者です 読者をやめる 読者になる 読者になる

jquery.jsを読み解くを見て勉強(第3回分)

jQuery JavaScript

id:lesamoureuses:20080805:1217957807
id:lesamoureuses:20080809:1218269672
に引き続き第3回分

jQuery.fn.map

jQuery.mapに自身のjQueryオブジェクトと引数で受け取ってるcallback関数を渡し、
その結果(ただの配列)をスタックに入れてjQueryオブジェクトにして返してる

jQuery.fn.mapとjQuery.mapの違い

例えば、

jQuery('div').map(function (index, domElement) {
  console.debug(this); // domElementと同じ
  return domElement;
});

は、thisとdomElementは同じものになり、戻り値はjQueryオブジェクト。
一方、

jQuery.map(jQuery('div'), function(domElement, index){
  console.debug(this);          // window
  console.debug(domElement);    // jQuery.fn.mapのdomElementと同じ
  return domElement;
});

はthisとdomElementは違うものになり、戻り値はただの配列。

jQuery.fn.domManip

jQuery.fn.append,jQuery.fn.prependなどで使われていて、
argsがjQery.fn.appendなどに渡された引数、
callbackがjQery.fn.appendなどの処理本体になってる。

clone = this.length > 1

のthisはjQueryオブジェクト。
対象となる要素が複数あればtrue、1つもしくはナシならばfalseになる


487行目this.eachで対象となる要素全てに処理。
function(){}の中に入って、thisは一つ一つの要素になる。
例えば、

$('p').append('<span>hello</span>', 'world')

だと、$('p')でページ内の<p>を全て保持し、functionの中のthisは

それぞれ。

0489:        elems = jQuery.clean( args, this.ownerDocument );

でargsをjQuery.cleanに渡し、パラメータの文字列をDOMにしてelemsに入れる。
さっきの例だと、elemsはとtextNodeの配列になる。


次。table処理。

0497:      if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
0498:        obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );

jQuery.fn.appendやjQuery.fn.prependでtableの中に要素を追加することがあるので、
パラメータのtableがtrueになる。

$('table').append('<tr>row</tr>');

みたいなときにthisは<table>、elems[0]が<tr>なので当てはまる。


502行目。
elemsの要素分だけループ処理。
次の行。

0503:        var elem = clone ?
0504:          jQuery( this ).clone( true )[0] :
0505:          this;

cloneがtrueの時、つまり、

$('p').append('<span>hello</span>', 'world')

としたときに、ページ内に対象となる<p>が一つしかない時は、
パラメータの要素を一度だけ追加すれば良いのでthisで良い。
<p>が複数あった場合はelemsを何度も使いまわすのでcloneを作る。


最後513行目。

0513:            scripts = scripts.add( jQuery( "script", elem ).remove() );

jQuery( "script", elem )は$(elem).find("script")と同じ。
パラメータの要素の子要素にscriptがあればそれを取り出し、
remove()でページから削除。

jQuery.extend,jQuery.fn.extend

初めの引数がtrueの場合は階層深くまで上書きをする。

var obj1 = {
    d1: {
        d2_1: 'a',
        d2_2: 'a'
    }
}
var obj2 = {
    d1: { 
        d2_1: 'b'
    }
}

とあった場合、

$.extend(true,obj1,obj2)

だと、

var obj1 = {
    d1: {
        d2_1: 'b',
        d2_2: 'a'
    }
}

となり、

$.extend(obj1,obj2)

だと、

var obj1 = {
    d1: {
        d2_1: 'b',
    }
}

という風にd1が階層を考慮されずに上書きされる。

jQuery.isFunction

prototype.jsのようにtypeofでfunctionかどうかを判別しようとすると、

typeof document.createElement('object').getAttribute
typeof document.createElement('input').focus

のような例がIEでは「object」と判断されるためダメ。

jQuery.each

object.length == undefined

で、ハッシュの場合と配列の場合の動きを分けてる。
ハッシュはlengthプロパティがないので「var name in object」でループ。
配列はlengthプロパティがあって「var i = 0, length = object.length; i < length; i++」でループ。