2016-02-24 2 views
13

Es ist relativ einfach, Änderungen in einem Array in Javascript zu beobachten.Erkennen von Änderungen in einem Javascript-Array mit dem Proxy-Objekt

Eine Methode, die ich verwenden, ist wie folgt:

// subscribe to add, update, delete, and splice changes 
Array.observe(viewHelpFiles, function(changes) { 
    // handle changes... in this case, we'll just log them 
    changes.forEach(function(change) { 
    console.log(Object.keys(change).reduce(function(p, c) { 
     if (c !== "object" && c in change) { 
     p.push(c + ": " + JSON.stringify(change[c])); 
     } 
     return p; 
    }, []).join(", ")); 
    }); 
}); 

Allerdings habe ich vor kurzem gelesen, dass Array.observe ist veraltet, und wir sollten die proxy object instead.

verwenden Wie können wir Änderungen in einem Array das Proxy-Objekt erfassen ? Ich bin nicht in der Lage, irgendwelche Beispiele zu finden, die an der Ausarbeitung interessiert sind.

+0

ich für "proxy beobachten" in Google sah, bekam diese https://gist.github.com/ebidel/1b553d571f924da2da06 – elclanrs

+1

Beachten Sie, dass Proxies derzeit nur in unterstützt wird Firefox, und ein paar Transpilers, ist nicht etwas, was Sie in Produktionscode verwenden würden. – adeneo

+0

Proxy wird jetzt in allen gängigen Browsern mit Ausnahme von Internet Explorer unterstützt. –

Antwort

23

Von dem, was ich aus der MDN page lesen kann, können Sie einen allgemeinen Handler erstellen, wo Sie alle Änderungen an einem Objekt behandeln können.

In gewisser Weise schreiben Sie einen Interceptor, der jedes Mal eingreift, wenn Sie einen Wert vom Array erhalten oder einen Wert setzen. Sie können dann Ihre eigene Logik schreiben, um den Änderungen zu folgen.

var arrayChangeHandler = { 
 
    get: function(target, property) { 
 
    console.log('getting ' + property + ' for ' + target); 
 
    // property is index in this case 
 
    return target[property]; 
 
    }, 
 
    set: function(target, property, value, receiver) { 
 
    console.log('setting ' + property + ' for ' + target + ' with value ' + value); 
 
    target[property] = value; 
 
    // you have to return true to accept the changes 
 
    return true; 
 
    } 
 
}; 
 

 
var originalArray = []; 
 
var proxyToArray = new Proxy(originalArray, arrayChangeHandler); 
 

 
proxyToArray.push('Test'); 
 
console.log(proxyToArray[0]); 
 

 
// pushing to the original array won't go through the proxy methods 
 
originalArray.push('test2'); 
 

 
// the will however contain the same data, 
 
// as the items get added to the referenced array 
 
console.log('Both proxy and original array have the same content? ' 
 
    + (proxyToArray.join(',') === originalArray.join(','))); 
 

 
// expect false here, as strict equality is incorrect 
 
console.log('They strict equal to eachother? ' + (proxyToArray === originalArray));

Welche gibt dann:

getting push for 
getting length for 
setting 0 for with value Test 
setting length for Test with value 1 
getting 0 for Test 
Test 

Der Nachteil für den Proxy, dass alles, das auf ein Objekt definiert ist, wird abgefangen werden, die beobachtet werden kann, bei der Verwendung von die push Methode.

Das ursprüngliche Objekt, das proxied wird, mutiert nicht, und Änderungen am ursprünglichen Objekt werden nicht vom Proxy abgefangen.

+1

Ein Vorbehalt, der in IE11 nicht unterstützt wird. – Chexpir

+2

@Chexpir wahr, nach MDN ist es sogar völlig nicht von IE unterstützt, aber es sollte von Edge unterstützt werden, das ist der aktuelle MS-Browser – Icepickle

+0

Aber Sie beobachten das Array überhaupt nicht, erstellen Sie einen Proxy und der Proxy leitet Änderungen weiter zu dem Array. Die Frage ist, wie man das Array selbst beobachtet. Das Benennen des Proxy "arrayToObserve" ist irreführend. Dieser Proxy und das Array sind zwei völlig verschiedene Objekte. – Winchestro

0

Sie können somthing tun wie dieser

new Proxy([], { 
    get(target, prop) { 
     const val = target[prop]; 
     if (typeof val === 'function') { 
      if (['push', 'unshift'].includes(prop)) { 
       return function (el) { 
        console.log('this is a array modification'); 
        return Array.prototype[prop].apply(target, arguments); 
       } 
      } 
      if (['pop'].includes(prop)) { 
       return function() { 
        const el = Array.prototype[prop].apply(target, arguments); 
        console.log('this is a array modification'); 
        return el; 
       } 
      } 
      return val.bind(target); 
     } 
     return val; 
    } 
}); 
Verwandte Themen