栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何观察阵列变化?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何观察阵列变化?

有一些选择…

1.覆盖推送方法

走快速而肮脏的路线,您可以覆盖

push()
数组1的方法:

Object.defineProperty(myArray, "push", {  enumerable: false, // hide from for...in  configurable: false, // prevent further meddling...  writable: false, // see above ^  value: function () {    for (var i = 0, n = this.length, l = arguments.length; i < l; i++, n++) {     RaiseMyEvent(this, n, this[n] = arguments[i]); // assign/raise your event    }    return n;  }});

1或者,如果要定位 所有
数组,则可以覆盖

Array.prototype.push()
。但是要小心;您环境中的其他代码可能不喜欢或期望这种修改。不过,如果所有内容听起来都很吸引人,请替换
myArray
Array.prototype

现在,这只是一种方法,并且有很多更改数组内容的方法。我们可能需要更全面的信息…

2.创建一个自定义的可观察数组

您可以创建自己的可观察数组,而不是覆盖方法。此特定实现拷贝的阵列到一个新的数组状物体并提供定制

push()
pop()
shift()
unshift()
slice()
,和
splice()
的方法
以及 定制索引访问器(条件是数组大小仅通过上述方法或一种修饰的
length
属性)。

function ObservableArray(items) {  var _self = this,    _array = [],    _handlers = {      itemadded: [],      itemremoved: [],      itemset: []    };  function defineIndexProperty(index) {    if (!(index in _self)) {      Object.defineProperty(_self, index, {        configurable: true,        enumerable: true,        get: function() {          return _array[index];        },        set: function(v) {          _array[index] = v;          raiseEvent({ type: "itemset", index: index, item: v          });        }      });    }  }  function raiseEvent(event) {    _handlers[event.type].forEach(function(h) {      h.call(_self, event);    });  }  Object.defineProperty(_self, "addEventListener", {    configurable: false,    enumerable: false,    writable: false,    value: function(eventName, handler) {      eventName = ("" + eventName).toLowerCase();      if (!(eventName in _handlers)) throw new Error("Invalid event name.");      if (typeof handler !== "function") throw new Error("Invalid handler.");      _handlers[eventName].push(handler);    }  });  Object.defineProperty(_self, "removeEventListener", {    configurable: false,    enumerable: false,    writable: false,    value: function(eventName, handler) {      eventName = ("" + eventName).toLowerCase();      if (!(eventName in _handlers)) throw new Error("Invalid event name.");      if (typeof handler !== "function") throw new Error("Invalid handler.");      var h = _handlers[eventName];      var ln = h.length;      while (--ln >= 0) {        if (h[ln] === handler) {          h.splice(ln, 1);        }      }    }  });  Object.defineProperty(_self, "push", {    configurable: false,    enumerable: false,    writable: false,    value: function() {      var index;      for (var i = 0, ln = arguments.length; i < ln; i++) {        index = _array.length;        _array.push(arguments[i]);        defineIndexProperty(index);        raiseEvent({          type: "itemadded",          index: index,          item: arguments[i]        });      }      return _array.length;    }  });  Object.defineProperty(_self, "pop", {    configurable: false,    enumerable: false,    writable: false,    value: function() {      if (_array.length > -1) {        var index = _array.length - 1,          item = _array.pop();        delete _self[index];        raiseEvent({          type: "itemremoved",          index: index,          item: item        });        return item;      }    }  });  Object.defineProperty(_self, "unshift", {    configurable: false,    enumerable: false,    writable: false,    value: function() {      for (var i = 0, ln = arguments.length; i < ln; i++) {        _array.splice(i, 0, arguments[i]);        defineIndexProperty(_array.length - 1);        raiseEvent({          type: "itemadded",          index: i,          item: arguments[i]        });      }      for (; i < _array.length; i++) {        raiseEvent({          type: "itemset",          index: i,          item: _array[i]        });      }      return _array.length;    }  });  Object.defineProperty(_self, "shift", {    configurable: false,    enumerable: false,    writable: false,    value: function() {      if (_array.length > -1) {        var item = _array.shift();        delete _self[_array.length];        raiseEvent({          type: "itemremoved",          index: 0,          item: item        });        return item;      }    }  });  Object.defineProperty(_self, "splice", {    configurable: false,    enumerable: false,    writable: false,    value: function(index, howMany  ) {      var removed = [],          item,          pos;      index = index == null ? 0 : index < 0 ? _array.length + index : index;      howMany = howMany == null ? _array.length - index : howMany > 0 ? howMany : 0;      while (howMany--) {        item = _array.splice(index, 1)[0];        removed.push(item);        delete _self[_array.length];        raiseEvent({          type: "itemremoved",          index: index + removed.length - 1,          item: item        });      }      for (var i = 2, ln = arguments.length; i < ln; i++) {        _array.splice(index, 0, arguments[i]);        defineIndexProperty(_array.length - 1);        raiseEvent({          type: "itemadded",          index: index,          item: arguments[i]        });        index++;      }      return removed;    }  });  Object.defineProperty(_self, "length", {    configurable: false,    enumerable: false,    get: function() {      return _array.length;    },    set: function(value) {      var n = Number(value);      var length = _array.length;      if (n % 1 === 0 && n >= 0) {        if (n < length) {          _self.splice(n);        } else if (n > length) {          _self.push.apply(_self, new Array(n - length));        }      } else {        throw new RangeError("Invalid array length");      }      _array.length = n;      return value;    }  });  Object.getOwnPropertyNames(Array.prototype).forEach(function(name) {    if (!(name in _self)) {      Object.defineProperty(_self, name, {        configurable: false,        enumerable: false,        writable: false,        value: Array.prototype[name]      });    }  });  if (items instanceof Array) {    _self.push.apply(_self, items);  }}(function testing() {  var x = new ObservableArray(["a", "b", "c", "d"]);  console.log("original array: %o", x.slice());  x.addEventListener("itemadded", function(e) {    console.log("Added %o at index %d.", e.item, e.index);  });  x.addEventListener("itemset", function(e) {    console.log("Set index %d to %o.", e.index, e.item);  });  x.addEventListener("itemremoved", function(e) {    console.log("Removed %o at index %d.", e.item, e.index);  });  console.log("popping and unshifting...");  x.unshift(x.pop());  console.log("updated array: %o", x.slice());  console.log("reversing array...");  console.log("updated array: %o", x.reverse().slice());  console.log("splicing...");  x.splice(1, 2, "x");  console.log("setting index 2...");  x[2] = "foo";  console.log("setting length to 10...");  x.length = 10;  console.log("updated array: %o", x.slice());  console.log("setting length to 2...");  x.length = 2;  console.log("extracting first element via shift()");  x.shift();  console.log("updated array: %o", x.slice());})();

请参阅以供参考。

Object.[defineProperty()](https://developer.mozilla.org/en-US/docs/Web/Javascript/Reference/Global_Objects/Object/defineProperty)

这使我们更加接近,但仍不是防弹措施……这使我们能够:

3.代理

代理提供了另一种解决方案…允许您拦截方法调用,访问器等。最重要的是,您甚至不需要提供明确的属性名称就可以执行此操作…这将允许您测试任意的,基于索引的访问/分配。您甚至可以拦截属性删除。代理可以有效地让您
决定允许更改 之前 检查更改…除了在事后处理更改之外。

这是精简的示例:

(function() {  if (!("Proxy" in window)) {    console.warn("Your browser doesn't support Proxies.");    return;  }  // our backing array  var array = ["a", "b", "c", "d"];  // a proxy for our array  var proxy = new Proxy(array, {    apply: function(target, thisArg, argumentsList) {      return thisArg[target].apply(this, argumentList);    },    deleteProperty: function(target, property) {      console.log("Deleted %s", property);      return true;    },    set: function(target, property, value, receiver) {      target[property] = value;      console.log("Set %s to %o", property, value);      return true;    }  });  console.log("Set a specific index..");  proxy[0] = "x";  console.log("Add via push()...");  proxy.push("z");  console.log("Add/remove via splice()...");  proxy.splice(1, 3, "y");  console.log("Current state of array: %o", array);})();


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/416036.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号