ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript高度プログラミング学習ノート js高度スキル_基礎知識

JavaScript高度プログラミング学習ノート js高度スキル_基礎知識

WBOY
WBOYオリジナル
2016-05-16 18:01:56917ブラウズ

第18章 高度なスキル
1. 高度な関数
1.1 スコープセーフコンストラクター
①new演算子を使用せずに直接コンストラクターを呼び出すと、このオブジェクトの遅延バインディングにより、グローバルにマッピングされます。オブジェクト ウィンドウにオブジェクト プロパティ エラーが追加される原因となります。

コードをコピー コードは次のとおりです:

function person(name,age,job) {
this.name = 名前;
this.job = 仕事;
Var person("ジェイ",29,"歌手") ; // プロパティがウィンドウ オブジェクトに追加されます。


②スコープセーフコンストラクター


関数 人(名前,年齢,仕事){
if(人のこのインスタンス){
この.名前 = 名前;
この.年齢 = 年齢;
return new Person(name,age);
}
}


③上記のスコープセーフなコンストラクターを使用してパターンの継承を盗み、プロトタイプ チェーンの場合、この継承は壊れる可能性があります。
□ この問題は、コンストラクターのスチールをプロトタイプのチェーンまたは寄生構成と組み合わせると解決できます。



コードをコピー コードは次のとおりです。 function Polygon(side){
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 番目の関数呼び出しにより若干遅くなりますが、複数の条件が回避されるため、後続の呼び出しは高速になります。



コードをコピー


コードは次のとおりです。
function create XHR(){ if(XMLHttp リクエストのタイプ != "未定義"){ createXHR = function(){ 新しい XMLHttpRequest(); }else if(ActiveXObject のタイプ != "未定義") {
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(){
return fn.apply(context, argument); } ③バインドされた関数は通常の関数よりも多くのオーバーヘッドを必要としますまた、複数の関数呼び出しにより若干速度が低下するため、必要な場合にのみ使用するのが最適です。 1.4 関数のカリー化 定義: 1 つ以上のパラメーターが設定された関数を作成するために使用されます。関数カリー化の基本的なアプローチは関数バインディングと同じで、クロージャを使用して関数を返します。 2 つの違いは、関数が呼び出されるときに、return 関数でもいくつかの受信パラメータを設定する必要があることです。



コードをコピー


コードは次のとおりです:

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 関連の操作を実行しすぎると、ブラウザがハングしたりクラッシュしたりする可能性があります。
②関数スロットルのアイデア: 一部のコードは中断せずに実行できません。 🎜>
コードをコピー


コードは次のとおりです:
varprocessor = { timeoutId : null, / /実際の処理MethodperformProcessing: function(){ //実際の実行メソッド
},
//初期処理呼び出しメソッド
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);
};
ドラッグドロップを返す;
}();
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。