ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript のデータ構造とアルゴリズム (2): Queue_javascript スキル

JavaScript のデータ構造とアルゴリズム (2): Queue_javascript スキル

WBOY
WBOYオリジナル
2016-05-16 15:53:591150ブラウズ

キューは、一方の端で挿入操作のみを許可し、もう一方の端で削除操作のみを許可する線形リストです。キューは先入れ先出し (FIFO) データ構造です。

キューはプログラム設計で非常に頻繁に使用されます。JavaScript はシングルスレッドであるため、一度に 1 つのタスクのみを実行でき、非同期メカニズムも混合されます。

次に問題:

1. 非同期操作が実行されると、同期コードはまだ継続しており、同期コードは非同期に依存するため、当然エラーが発生します

2. 複数の同期タスクが異なる期間で呼び出されます

jQuery アニメーションでは、連続したアニメーション コードを記述することがよくあります

$book.animate({
  opacity: 0.25,
}).animate({
  opacity: 0.5
}).animate({
  opacity: 1
})

直感的には、最初のアニメーションが終了すると要素の不透明度が 0.25 になり、次に 2 番目のアニメーションが実行され始めて要素の不透明度が 0.5 になる、というようになります。しかし実際には、ここには本質的な問題があり、アニメーションは非同期で呼び出され、animate メソッドは同期的に実行されるため、jQuery はアニメーション用に特別に設計された queue メソッドも提供する必要があります。

キューは特殊な線形リストでもあり、JavaScript では配列を直接使用して、配列の末尾に要素を追加したり、shift() メソッドで要素を削除したりできます。配列の最初の要素。


function Queue() {
  this.dataStore = [];
  this.enqueue  = enqueue;
  this.dequeue  = dequeue;
  this.first   = first;
  this.end    = end;
  this.toString = toString;
  this.empty   = empty;
}

///////////////////////////
// enqueue()方法向队尾添加一个元素: //
///////////////////////////
function enqueue(element) {
  this.dataStore.push(element);
}

/////////////////////////
// dequeue()方法删除队首的元素: //
/////////////////////////
function dequeue() {
  return this.dataStore.shift();
}

/////////////////////////
// 可以使用如下方法读取队首和队尾的元素: //
/////////////////////////
function first() {
  return this.dataStore[0];
}

function end() {
  return this.dataStore[this.dataStore.length - 1];
}

/////////////////////////////
// toString()方法显示队列内的所有元素 //
/////////////////////////////
function toString() {
  var retStr = "";
  for (var i = 0; i < this.dataStore.length; ++i) {
    retStr += this.dataStore[i] + "\n";
  }
  return retStr;
}

////////////////////////
// 需要一个方法判断队列是否为空 //
////////////////////////
function empty() {
  if (this.dataStore.length == 0) {
    return true;
  } else {
    return false;
  }
}

var q = new Queue();
q.enqueue("Aaron1");
q.enqueue("Aaron2");
q.enqueue("Aaron3");

console.log("队列头: " + q.first());  //("Aaron1");
console.log("队列尾: " + q.end()); //("Aaron3");

キューはリニア ストレージを使用するため、最初の人がチケットを購入すると、後続の人は自然に 1 スペースずつ進み、キュー全体が関与するなど、シーケンシャル ストレージにはいくつかの欠点があります。の各メンバーは前に進む必要がありますが、JavaScript のキューは配列によって記述されており、最下層がいくつかの欠点を解決しています。もちろん、単一リンクされたリスト構造の実装に使用できる配列など、検索アルゴリズムに関する問題もあります。ここでは JavaScript キューについてのみ説明します

jQuery をシミュレートし、キューを使用してアニメーションを実装します


<div id="div1" style="width:100px;height:50px;background:red;cursor:pointer;color:#fff;text-align:center;line-height:50px;">点击</div>

(function($) {

  window.$ = $;

})(function() {

  var rquickExpr = /^(&#63;:#([\w-]*))$/;

  function aQuery(selector) {
    return new aQuery.fn.init(selector);
  }

  /**
   * 动画
   * @return {[type]} [description]
   */
  var animation = function() {
    var self = {};
    var Queue = []; //动画队列
    var fireing = false //动画锁
    var first = true; //通过add接口触发

    var getStyle = function(obj, attr) {
      return obj.currentStyle &#63; obj.currentStyle[attr] : getComputedStyle(obj, false)[attr];
    }

    var makeAnim = function(element, options, func) {
      var width = options.width
        //包装了具体的执行算法
        //css3
        //setTimeout
      element.style.webkitTransitionDuration = '2000ms';
      element.style.webkitTransform = 'translate3d(' + width + 'px,0,0)';

      //监听动画完结
      element.addEventListener('webkitTransitionEnd', function() {
        func()
      });
    }

    var _fire = function() {
      //加入动画正在触发
      if (!fireing) {
        var onceRun = Queue.shift();
        if (onceRun) {
          fireing = true;
          //next
          onceRun(function() {
            fireing = false;
            _fire();
          });
        } else {
          fireing = true;
        }
      }
    }

    return self = {
      //增加队列
      add: function(element, options) {
        Queue.push(function(func) {
          makeAnim(element, options, func);
        });

        //如果有一个队列立刻触发动画
        if (first && Queue.length) {
          first = false;
          self.fire();
        }
      },
      //触发
      fire: function() {
        _fire();
      }
    }
  }();


  aQuery.fn = aQuery.prototype = {
    run: function(options) {
      animation.add(this.element, options);
      return this;
    }
  }

  var init = aQuery.fn.init = function(selector) {
    var match = rquickExpr.exec(selector);
    var element = document.getElementById(match[1])
    this.element = element;
    return this;
  }

  init.prototype = aQuery.fn;

  return aQuery;
}());

//dom
var oDiv = document.getElementById('div1');

//调用
oDiv.onclick = function() {
  $('#div1').run({
    'width': '500'
  }).run({
    'width': '300'
  }).run({
    'width': '1000'
  });
};

テスト


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。