第18章 高度なスキル
1. 高度な関数
1.1 スコープセーフコンストラクター
①new演算子を使用せずに直接コンストラクターを呼び出すと、このオブジェクトの遅延バインディングにより、グローバルにマッピングされます。オブジェクト ウィンドウにオブジェクト プロパティ エラーが追加される原因となります。
function person(name,age,job) {
this.name = 名前;
this.job = 仕事;
Var person("ジェイ",29,"歌手") ; // プロパティがウィンドウ オブジェクトに追加されます。
②スコープセーフコンストラクター
関数 人(名前,年齢,仕事){
if(人のこのインスタンス){
この.名前 = 名前;
この.年齢 = 年齢;
return new Person(name,age);
}
}
③上記のスコープセーフなコンストラクターを使用してパターンの継承を盗み、プロトタイプ チェーンの場合、この継承は壊れる可能性があります。
□ この問題は、コンストラクターのスチールをプロトタイプのチェーンまたは寄生構成と組み合わせると解決できます。
if(このインスタンスの Polygon){
this.sides = 面;
this.getArea = function{return 0;}else{
return new Polygon(sides);
}
function Rectangle(width,height){
Polygon.call(this,2);
this.width = width;
this. getArea = function (){
return this.width * this.height;
}
Rectangle.prototype = new Polygon();
var rectangle(5, 10);
alert(rect.sides); //2
1.2 遅延ロード関数
① 遅延ロードとは、関数の実行の分岐が最初の呼び出しのみであることを意味します。いつ。最初の呼び出し中に、関数は適切な方法で実行される別の関数で上書きされるため、元の関数への呼び出しは実行の分岐を経由する必要がありません。
■利点:
□実際に関数が呼び出されたときにのみ適切なコードが実行されます。
□この関数への最初の呼び出しは、追加の 2 番目の関数呼び出しにより若干遅くなりますが、複数の条件が回避されるため、後続の呼び出しは高速になります。
コードをコピー
コードは次のとおりです。
createXHR = function(){
if(引数の種類.callee.activeXString != "string"){
var バージョン = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0" ,"MSXML2 .XMLHttp"];
for(vai I = 0, len = version.length; I
try{
Var xhr = new ActiveXObject(version[i] );
Arguments.callee.activeXString = version[i];
Return xhr;
}catch(ex){
//skip
}
}
return new ActiveXObject(arguments.callee.activeXString);
}else{
createXHR = function(){
throw new Error("XHR オブジェクトがありません。"); 🎜>} ;
}
return createXHR();
}
1.3 関数バインディング
① 関数バインディング 関数を作成するには、特定の関数にパラメータを指定します。環境 別の関数を呼び出します。
②単純なbind()関数は関数と環境を受け入れ、指定された環境で指定された関数を呼び出す関数を返し、すべてのパラメータをそのまま渡します。
コードをコピー
コードは次のとおりです。
function binding(fn, context){
return function(){
コードをコピー
コードは次のとおりです:
function binding(fn, context){
var args = Array.prototype.slice.call(arguments, 2);
return function(){
var innerArgs = Array.prototype .slice.call(arguments);
var FinalArgs = args.concat(innerArgs);
return fn.apply(context,finalArgs);
2. 高度なタイマー
①JavaScript はシングルスレッドプログラムであり、タイマーはインターバル後にコードをキューに追加します。
②一連のコードを実行した後、JavaScript プロセスは短時間復帰し、ページ上で他の処理を実行できるようになります。
2.1 タイマーの重複
①setInterval() は、このタイマーのコードの他のインスタンスがない場合にのみ、タイマー コードをキューに追加します。
□一部の区間がスキップされます。
□複数のタイマー コードの実行間隔が予想よりも短い可能性があります。
② setInterval() の 2 つの欠点を回避し、連鎖した setTimeout() 呼び出しを使用します。
setTimeout(function(){
//処理
if(condition){
setTimeout(arguments.callee, interval);
}
} , 間隔);
2.2 プロセスの放棄
① JavaScript の長時間実行スクリプトの制限: コードが特定の時間または特定のステートメント数を超えて実行される場合、コードは実行を継続しません。 。
②関数の完了に 200 ミリ秒以上かかる場合は、タイマーを使用できる一連の小さなタスクに分割するのが最善です。
③配列ブロッキング技術: 処理対象のキューを作成し、タイマーを使用して次の処理対象を取り出し、さらにタイマーを設定します。
関数チャンク(配列、プロセス、コンテキスト) {
setTimeout(function(){
var item = array.shift();
process.call(context,item);
if(array.length>0){
setTimeout (arguments.callee, 100);
}
}
}
2.3 関数スロットリング
①DOM 操作は、非 DOM 操作よりも多くのメモリと CPU 時間を必要とします。 DOM 関連の操作を実行しすぎると、ブラウザがハングしたりクラッシュしたりする可能性があります。
②関数スロットルのアイデア: 一部のコードは中断せずに実行できません。 🎜>
コードをコピー
コードは次のとおりです:
},
//初期処理呼び出しメソッド
process: function(){
clearTimeout(this. timeoutId);
var that = this;
this.timeoutId = setTimeout(function(){
that.performProcessing();
}
};
//実行を開始してみます
Processor.process();
□簡易モード
function throttle(method,context){
clearTimeout(mehtod.tId); tId = setTimeout(function(){
method.call(context);
},100);
}
3. イベントは設計ですオブザーバーと呼ばれるパターン。これは疎結合コードを作成するための手法です。
□オブジェクトは、オブジェクトのライフサイクルの興味深い瞬間が到来したことを示すイベントを発行できます。
□他のオブジェクトはオブジェクトを観察し、興味深い瞬間を待つことができます。コードを実行して応答します。
②観察者パターンは、主体と観察者の 2 種類のオブジェクトで構成されます。
□サブジェクトはイベントを公開する責任があり、オブザーバーはこれらのイベントをサブスクライブすることでサブジェクトを観察します。
□主体は観察者について何も知りません。観察者が存在しなくても独立して存在し、正常に機能します。
③カスタムイベント: イベントを管理するオブジェクトを作成し、他のオブジェクトがそれらのイベントをリッスンできるようにします。
コードをコピー
コードは次のとおりです:
function EventTarget(){
this.handlers = {};
}
EventTarget.prototype = {
constructor : EventTarget,
addHandler : function(type,handler){
if(typeof this.handlers[type] == "未定義"){
this.handlers[タイプ] = [];
}
this.handlers[type].push(handler);
},
fire : function(event){
if(!event.target){
event.target = this;
}
if(this.handlers[event.type] 配列のインスタンス){
var handlers = this.handlers[event.type];
for(var i=0,len=handlers.length; ihandlers[i](event);
}
}
},
removeHandler : function(type, handler){
if(this.handlers[type]instanceof Array){
var handlers = this.handlers[タイプ];
for(var i=0,len=handlers.length; iif(handlers[i] === ハンドラー){
break;
}
}
Handlers.splice(i,1);
}
};
④EventTarget タイプの独自定義イベントを使用する場合は次のように使用できます:
function handleMessage(event){
alert("メッセージを受信しました:"event.message);
}
//创建一个新对オブジェクト
var target = new EventTarget();
//追加一个イベント处理程序
target.addHandler("message",handleMessage);
//触発イベント
target.fire({type:"message",message:"hello world!"});
//删除イベント处理程序
target.removeHandler("message",handleMessage);
⑤使用例
function 人(名前,年齢){
eventTarget.call(this);
this.name = 名前;
this.age = 年齢;
}
inheritPrototype(person, EventTarget);
person.prototype.say = function(message){
this.fire({type:"message", message:message});
};
function handleMessage(event){
alert(event.target.name "says: "event.message);
}
//创建新人
var person = new person("Nicholas",29);
//追加一个イベント处理程序
person.addHandler("message",handleMessage);
//このオブジェクト上で 1 つのメソッドを使用して、メッセージ イベントをトリガーします
person.say("Hi there");
4.拖放
機能:①拖放②追加済自定义イベント
var DragDrop = function(){
varragdrop = new EventTarget();
var ドラッグ = null;
var diffX = 0;
var diffY = 0;
function handleEvent(event){
//イベントと对オブジェクトを取得
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
//イベントの種類を決定します
switch(event.type){
case "mousedown" :
if(target.className.indexOf("draggable")>-1){
ドラッグ = ターゲット;
diffX = events.clientX - target.offsetLeft;
diffY = events.clientY - target.offsetTop;
dragdorp.fire(
{
type:"dragstart",
ターゲット : ドラッグ中,
x :event.clientX,
y :event.clientY
}
);
休憩;
case "mousemove" :
if(dragging !== null){
//获取イベント
event = EventUtil.getEvent(event);
// 位置指定
dragging.style.left = (event.clientX - diffX) "px";
dragging.style.top = (event.clientY - diffY) "px";
//触発自定义イベント
dragdrop.fire(
{
type : "drag",
target : dargging,
x :event.clientX,
y :イベント.clientY
}
);
}
休憩;
case "mouseup" :
dargdorp.fire(
{
type : "dragend",
target : ドラッグ,
x : events.clientX,
y : イベント.clientY
}
);
ドラッグ = null;
休憩;
}
}
//パブリック インターフェイス
dragdrop.enable = function() {
EventUtil.addHandler(document, "mousedown", handleEvent);
EventUtil.addHandler(document, "mousemove", handleEvent);
EventUtil.addHandler(document, "mouseup", handleEvent);
};
dragdrop.disable = function(){
EventUtil.removeHandler(document, "mousedown", handleEvent);
EventUtil.removeHandler(document, "mousemove", handleEvent);
EventUtil.removeHandler(document, "mouseup", handleEvent);
};
ドラッグドロップを返す;
}();