ExtJsソース分析と学習—ExtJsコアコード(三)


Extはjavascriptのいくつかのオブジェクトを拡張しました.主にString、Aray、Functionがあります.以下はExt.jsで述べた方法だけを紹介します.他の方法は後で紹介します.
 
ExtはStringで拡張された方法formatであり、この方法はStringの静的方法(クラス方法)であり、文字列中の特殊な書き方({0}、{1}を指定された変数で置き換えることができる.
 
//         ,           。          ,      {0},{1}...{n}
 //      。
 //var cls = 'my-class', text = 'Some text';
 //var s = String.format('{0} '  '{1}', cls, text);
    //s      :s now contains the string: 'my-class'   'Some text'

    format : function(format){
        var args = Ext.toArray(arguments, 1);
        return format.replace(/\{(\d+)\}/g, function(m, i){
            return args[i];
        });
    }

   ExtはArayのために拡張された方法indexOfとremoveであり、この2つの方法はそれぞれインデックスとサブ要素から対応する要素を削除することを実現している.
Ext.applyIf(Array.prototype, {
    /**
     * Checks whether or not the specified object exists in the array.
     * @param {Object} o The object to check for
     * @param {Number} from (Optional) The index at which to begin the search
     * @return {Number} The index of o in the array (or -1 if it is not found)
     */
    indexOf : function(o, from){
        var len = this.length;
        from = from || 0;
        from += (from < 0) ? len : 0;
        for (; from < len; ++from){
            if(this[from] === o){
                return from;
            }
        }
        return -1;
    },

    /**
     * Removes the specified object from the array.  If the object is not found nothing happens.
     * @param {Object} o The object to remove
     * @return {Array} this array
     */
    remove : function(o){
        var index = this.indexOf(o);
        if(index != -1){
            this.splice(index, 1);
        }
        return this;
    }
});

 
編集者は実際の開発において、よく次の二つの方法を使います.
 
/**
  *       
  * @param {} index     
  * @param {} o     
  * @return {}
  */
 insert : function (index,o){
  if(index <= 0){
            return this.unshift(o);//      
        }
        if(index >= this.length){
            return this.push(o);//      
        }
        var sub = this.slice(index, this.length);
        this.length = index;
        this.push(o);
        for(var i = 0; i < sub.length; i++){
         this.push(sub[i]);
        }
        return this;
 },
 
 /**
  *           
  * @param {} index
  * @return {}
  */
 removeAt : function(index){
        if(index != -1){
            this.splice(index, 1);
        }
        return this;
    }
 
以下の拡張String法も有用である.
Ext.applyIf(String,{
 
 /**
  *             -  
  * alert(humpToConnector('aaaBbbCcc','-')); //return aaa-bbb-ccc
  * @param {} str
  * @param {} conj
  * @return {}
  */
    humpToConnector : function(str, conj){
  //str = !str ? str : String(str);
  var index = str.search(/[A-Z]/);
  if (index >= 0) {
   var c = str.charAt(index);
   return String.humpToConnector(str.substring(0, index) + conj
       + c.toLowerCase() + str.substring(index + 1), conj);
  } else {
   return str;
  }
 }
});
 
ExtのFunctionへの拡張
 
createInterceptor方法
createInterceptor : function(fcn, scope){
        var method = this;
        return !Ext.isFunction(fcn) ?
                this :
                function() {
                    var me = this,
                        args = arguments;
                    fcn.target = me;
                    fcn.method = method;
                    return (fcn.apply(scope || me || window, args) !== false) ?
                            method.apply(me || window, args) :
                            null;
                };
    },
 
この方法は、ブロックのような機能を実現し、伝達パラメータfcnは、元の関数の前に呼び出される.fcnの戻り値がfalseである場合、元の関数は呼び出されない.すなわち関数fcnでブロックした場合、fcnがfalseに戻るとブロックされ、trueが実行されます.方法の一部を説明します.
 
var method=thisは、Function.prototypeに拡張されているので、そのprototypeに掛けられているすべての関数は、関数内のthisがFunctionであり、関数自体です.次の例を見てください
Function.prototype.test = function(){
	alert(this);
};
function fn(){return 'test';}
fn.test();
  結果出力
function fn(){
    return「test」
)
つまり、thisはfn関数そのものです.
 
!Ext.isFunction(fcn)は、この条件は、伝達パラメータfcnが一つのfunctionでない場合、直接にthisに戻り、thisは関数自体であることを示している.あるいは、この時はブロックがなく、そのまま関数自体に戻ります.
 
fcnが一つのfunctionである場合、「:」後の分岐が実行され、このときfcnに2つの属性target,methodが追加されます.targetは私で、私はthisです.
この時のthisは何ですか?多くはwindowですが、全体のfunctionが対象属性として存在する場合、thisはその対象です.誰がcreateIntercepterを呼び出しましたか?methodは誰ですか?例えば:
 
function oldFn(){
	alert('test');
}
function ret(){
	return false;
}
var newFn = oldFn.createInterceptor(ret);
newFn();
oldFnはcreateInterceptor方法を継承し、それを呼び出しました.パラメータはretです.この時createInterceptorの内部のmethod、fcn.methodはoldFnです.私は、fcn.targetはwindowオブジェクトです.次のようにします.私、fcn.targetはobjです.
 
function oldFn(){
	alert('test');
}
function ret(){
	return false;
}
var obj = {name:'jack'};
obj.method = oldFn.createInterceptor(ret);
obj.method();
  (fcn.appy)は、伝えられたパラメータfcnが実行され、実行コンテキストが優先的にscopeであり、次は私であり、最後はwindowである.返した結果はfalseに等しくないので、methodを実行します.methodはコンテキストを実行して先に私で、私が存在しないのはwindowです.
 
政府の例を張り出します.
var sayHi = function(name){
    alert('Hi, ' + name);
}

sayHi('Fred'); // alerts "Hi, Fred"

// create a new function that validates input without
// directly modifying the original function:
var sayHiToFriend = sayHi.createInterceptor(function(name){
    return name == 'Brian';
});

sayHiToFriend('Fred');  // no alert
sayHiToFriend('Brian'); // alerts "Hi, Brian"
 
この例はcreateIntercepterにあります. fcn.appyは直接実行に相当します.
function{name}
    return name='Brian'
)
関数を別のオブジェクトに結び付けて実行します.
methodは実際にsayHiです.
 
createCallback方法
 
//        ,           :arguments[0],...
    createCallback : function(/*args...*/){
        // make args available, in function below
        var args = arguments,
            method = this;
        return function() {
            return method.apply(window, args);
        };
    },
 
この方法は非常に有用であり,簡単に実現する.新しい関数を返します.新しい関数ではmethodを実行します.外部のパラメータを転送します.初心者はよく  イベントのパラメータにこだわる .createCallbackはDOM事件のhandler(モニター)への伝来問題を解決しました.createCallbackはDOMイベントのhandlerだけではなく、完全にカスタマイズできます.自分のデザインは 観察者モードです. APIつまり、各クラスは自分のイベントを持っています.  LtMaps ,属性を持つ以外にも、マップを移動したり、地図を拡大したりするイベントがたくさんあります.Extの多くのUIコンポーネントもこのようなモードであり、Ext.Panelはafterlayout、closeなどのイベントを有する.
これらの事件にhanderを追加して、また参预したいです.createCallbackも使うかもしれません.
 
 
createDelegate方法
 
//        (    ),         obj。                 。
    //obj : Object (   )          。(optional) The object for which the scope is set 
    //args : Array (   )            。(       arguments)。(optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller) 
    //appendArgs : Boolean/Number(   )       true, args         ,          , args          。
    //     Array.prototype.slice(start,end)   ,            ,start,end    ,         
    createDelegate : function(obj, args, appendArgs){
        var method = this;
        return function() {
            var callArgs = args || arguments;
            if (appendArgs === true){
                callArgs = Array.prototype.slice.call(arguments, 0);
                callArgs = callArgs.concat(args);
            }else if (Ext.isNumber(appendArgs)){
                callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
                var applyArgs = [appendArgs, 0].concat(args); // create method call params
                Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
            }
            return method.apply(obj || window, callArgs);
        };
    },
 
createDelegateはcreateCallbackよりも強くて、コールバック関数の問題を解決できます.さらに制御できます.1、カスタムパラメータはデフォルトのパラメータを上書きしますか?  DOMイベント対象 handlerの最初のパラメータとして、カスタムパラメータの位置内部実装:自身(var method=this)を取って、新しいfunctionを返します.Functionは自身を呼び出して、コンテキストおよびパラメータ(calArgs)を指定します.このように簡単で、詳細はパラメータの制御にあります.1,Objとargsのみの場合は、コールバック関数のデフォルトパラメータ(DOMイベントオブジェクト)を上書きします.
<a href="#" id="aa">SINA</a>
<script type="text/javascript">
	var aa = document.getElementById('aa');
	function sayName(name){
		alert('hello, ' + name);
	}
	var sayName2 = sayName.createDelegate(aa,['jack']);
	aa.onclick = sayName2;
</script>
 2,3つのパラメータが全部渡されます.apendArgsがtrueの場合、デフォルトパラメータ(DOMイベントオブジェクト)の位置は変更されません.最初のパラメータのargsは最後になります.
<a href="#" id="aa">SINA</a>
<script type="text/javascript">
	var aa = document.getElementById('aa');
	function sayName(){		
		alert('      :' + arguments.length);
		alert('hello, ' + arguments[0]);
		alert('hi, ' + arguments[1]);
	}
	var sayName2 = sayName.createDelegate(aa,['jack'],true);
	aa.onclick = sayName2;
</script>
 3,3つのパラメータを転送します.appendArgsは数字の場合、カスタムパラメータの位置を指定します.
<a href="#" id="aa">SINA</a>
<script type="text/javascript">
	var aa = document.getElementById('aa');
	function sayName(name){		
		alert('      :' + arguments.length);
		alert('hello, ' + arguments[0]);
		alert('hi, '+ arguments[1]);
		alert('hi, '+ arguments[2]);
	}
	var sayName2 = sayName.createDelegate(aa,['jack','lily'],0);
	aa.onclick = sayName2;
</script>
 
deferメソッド
 
/**
     *        
     * @param {} millis     ,      (   0     )
     * @param {} obj (   ) fcn    (        window)
     * @param {} args (   )           (       arguments)
     * @param {} appendArgs (   )      true, args         ,          , args          
     * @return {Number}
     */
    defer : function(millis, obj, args, appendArgs){
        var fn = this.createDelegate(obj, args, appendArgs);
        if(millis > 0){
            return setTimeout(fn, millis);
        }
        fn();
        return 0;
    }