#61 监听数组变化


  • 0
    administrators

    在前端的 MVVM 框架当中,我们经常需要监听数据的变化,而数组是需要监听的重要对象。请你完成 ObserverableArray,它的实例和普通的数组实例功能相同,但是当调用:

    • push
    • pop
    • shift
    • unshift
    • splice
    • sort
    • reverse

    这些方法的时候,除了执行相同的操作,还会把方法名打印出来。 例如:

    const arr = new ObserverableArray()
    
    arr.push('Good') // => 打印 'push',a 变成了 ['Good']
    

    注意,你不能修改 Array 的 prototype。还有函数 return 的值和原生的操作保持一致。


  • 0

    用Proxy求解就很简单了。。。

    function ObserverableArray(...p) {
      return new Proxy(new Array(...p), {
        get(target, property) {
          const ret = target[property]
          if (typeof ret === 'function')
            return function (...p){ console.log(property); return ret.apply(this, p) }
          return ret
        }
      })
    }
    

  • 0

    @CodeHz#61 监听数组变化 中说:

    Proxy

    不用Proxy要怎么做


  • 0

    @caffrey 比如直接用继承。。。然后覆盖那几个方法,顺便调用基类方法什么的


  • 0
    administrators

    这道题如果用 ES5 的继承方式,最好不要产生和对原生数组的 for in 操作不一致的行为。

    例如:

    var a = ObserverableArray()
    for (let key in a) console.log(key)
    

    原生数组是不糊把 push、pop、...这些方法遍历出来的。你的实现最好也不要遍历这些属性。


  • 0
    管理员

    调用push方法 console.log的次数不对?有点奇怪了这个报错

    function ObserverableArray() {
      return new Proxy([], {
        get(target, propKey) {
          typeof target[propKey] == 'function' && console.log(propKey);
          return target[propKey]
        }
      })
    }
    

  • 0
    administrators

    @陈小俊 这种方式其实是不符合题意的。

    这样会导致所有函数都会打印内容,例如 forEach,而题目只要求 7 个方法。


  • 0
    管理员

    @胡子大哈 哦哦


  • 1
    管理员

    function ObserverableArray() {
      return new Proxy([], {
        get(target, propKey) {
          const matArr = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
          matArr.indexOf(propKey) > -1 && console.log(propKey);
          return target[propKey]
        }
      })
    }
    

  • 0

    我觉得很奇怪,我的arrMethods如果是[],就是ac,如果是{},就是返回的是需要时数组0_1496665756372_upload-a5c0e414-b233-4a57-9a0e-4a554b9ad344

    function ObserverableArray (){
      var arr = new Array();
      var arrMethodsName = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
      var arrMethods = [];
      arrMethodsName.forEach(function(method, index) {
        let original = Array.prototype[method];
        arrMethods[method] = function () {
          console.log(`${method}`);
          return original.apply(this, arguments);
        }
      })
      arr.__proto__ = arrMethods;
      return arr;
    }
    

  • 0

    @ScriptOJ#61 监听数组变化 中说:

    MVVM

    // TODO
    class ObserverableArray{
    constructor(){
    //理代原生原
    let arr = new Array();
    let specials = ['push','pop','shift','unshift','splice','sort','reverse'];
    specials.forEach((method) => {
    arr[method] = function(){
    console.log(method);
    return Array.prototype[method].apply(this,arguments);
    };

    })
    return arr;
    

    }
    }


  • 0

    我直接把新的方法定义在ObserverableArray 的原型上,不知道为什么不行,结果是“调用 push 方法对数组的操作不正确”

    @ScriptOJ

    class ObserverableArray extends Array {
          constructor(...props) {
            super(...props);
          };
    
          push(arg) {
            console.log('push');
            return Array.prototype.push.call(this, arg);
          };
    
          pop() {
            console.log('pop');
            return Array.prototype.pop.call(this)
          };
    
          shift() {
            console.log('shift');
            return Array.prototype.shift.call(this)
          };
    
          unshift(arg) {
            console.log('unshift');
            return Array.prototype.unshift.call(this, arg)
          };
    
          splice(index, target, ...res) {
            console.log('splice');
            return Array.prototype.splice.call(this, index, target, ...res)
          };
    
          sort(callback) {
            console.log('sort');
            return Array.prototype.sort.call(this, callback)
          };
    
          reverse() {
            console.log('reverse');
            return Array.prototype.reverse.call(this)
          }
        }
    

  • 0

    @duola push是可以接受多个参数的


  • 0

    @dsize1 噢,是我忽略了,多谢


登录后回复
 

与 ScriptOJ 的连接断开,我们正在尝试重连,请耐心等待