Inhaltsverzeichnis
definePropety
Setter und Getter
watch API
Proxy
watch API 优化
Heim Web-Frontend js-Tutorial Detaillierte Einführung in defineProperty und Proxy in ES6 (Codebeispiel)

Detaillierte Einführung in defineProperty und Proxy in ES6 (Codebeispiel)

Nov 15, 2018 pm 04:59 PM
handler javascript 交互设计 函数 前端

Dieser Artikel bietet Ihnen eine detaillierte Einführung (Codebeispiel) zu defineProperty und Proxy. Ich hoffe, dass er für Sie hilfreich ist.

Wir haben alle mehr oder weniger das Wort „Datenbindung“ gehört. Der Schlüssel zur „Datenbindung“ liegt in der Überwachung von Datenänderungen, aber für ein solches Objekt: var obj = {value: 1}, woher wissen wir, obj Was hat sich geändert?

definePropety

ES5 stellt die Methode Object.defineProperty bereit, die eine neue Eigenschaft für ein Objekt definieren oder eine vorhandene Eigenschaft eines Objekts ändern und das Objekt zurückgeben kann.

Syntax

Object.defineProperty(obj, prop, descriptor)
Nach dem Login kopieren

Parameter

obj: 要在其上定义属性的对象。
prop:  要定义或修改的属性的名称。
descriptor: 将被定义或修改的属性的描述符。
Nach dem Login kopieren

Zum Beispiel:

var obj = {};
Object.defineProperty(obj, "num", {
    value : 1,
    writable : true,
    enumerable : true,
    configurable : true
});
//  对象 obj 拥有属性 num,值为 1
Nach dem Login kopieren

Obwohl wir es direkt hinzufügen können Eigenschaften und Werte, aber mit diesem Ansatz können wir mehr Konfigurationen vornehmen. Der Attributdeskriptor, der durch den dritten Parameterdeskriptor der Funktion

dargestellt wird, hat zwei Formen: Datendeskriptor und Zugriffsdeskriptor .

Beide haben die folgenden zwei Schlüsselwerte :

konfigurierbar

genau dann, wenn das konfigurierbare Attribut „Wann“ ist true, der Eigenschaftsdeskriptor kann geändert oder gelöscht werden. Der Standardwert ist falsch.

aufzählbar

Nur ​​wenn die Aufzählung des Attributs wahr ist, kann das Attribut im Aufzählungsattribut des Objekts erscheinen. Der Standardwert ist falsch.

Der Datendeskriptor verfügt außerdem über die folgenden optionalen Schlüsselwerte :

Wert

Der entsprechende Wert zu diesem Attribut. Kann jeder gültige JavaScript-Wert sein (Zahl, Objekt, Funktion usw.). Der Standardwert ist undefiniert.

beschreibbar

Diese Eigenschaft kann vom Zuweisungsoperator genau dann geändert werden, wenn beschreibbar der Eigenschaft wahr ist. Der Standardwert ist falsch.

Der Zugriffsdeskriptor verfügt außerdem über die folgenden optionalen Schlüsselwerte :

get

eins vorgesehen Die Attribut-Getter-Methode. Wenn kein Getter vorhanden ist, ist sie undefiniert. Der Rückgabewert dieser Methode wird als Attributwert verwendet. Der Standardwert ist undefiniert.

set

Eine Methode, die einen Setter für eine Eigenschaft bereitstellt. Wenn kein Setter vorhanden ist, ist er undefiniert . Diese Methode akzeptiert einen eindeutigen Parameter und weist der Eigenschaft den neuen Wert dieses Parameters zu. Der Standardwert ist undefiniert.

Es ist erwähnenswert:

Attributdeskriptoren müssen entweder Datendeskriptoren oder Zugriffsdeskriptoren sein, nicht beides gleichzeitig. Das heißt, Sie können:

Object.defineProperty({}, "num", {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: true
});
Nach dem Login kopieren

oder Sie können:

var value = 1;
Object.defineProperty({}, "num", {
    get : function(){
      return value;
    },
    set : function(newValue){
      value = newValue;
    },
    enumerable : true,
    configurable : true
});
Nach dem Login kopieren

, aber nicht:

// 报错
Object.defineProperty({}, "num", {
    value: 1,
    get: function() {
        return 1;
    }
});
Nach dem Login kopieren

Darüber hinaus sind alle Eigenschaftsdeskriptoren optional, das Deskriptorfeld ist jedoch erforderlich . Wenn Sie nichts konfigurieren, können Sie Folgendes tun:

var obj = Object.defineProperty({}, "num", {});
console.log(obj.num); // undefined
Nach dem Login kopieren

Setter und Getter

Der Grund, warum wir über defineProperty sprechen, ist, dass wir den Zugriffsdeskriptor get und set verwenden möchten. Diese beiden Methoden werden auch Getter und Setter genannt. Durch Getter und Setter definierte Eigenschaften werden als „Accessor-Eigenschaften“ bezeichnet.

Wenn ein Programm den Wert einer Accessor-Eigenschaft abfragt, ruft JavaScript die Getter-Methode auf. Der Rückgabewert dieser Methode ist der Wert des Attributzugriffsausdrucks. Wenn ein Programm den Wert einer Accessor-Eigenschaft festlegt, ruft JavaScript die Setter-Methode auf und übergibt den Wert auf der rechten Seite des Zuweisungsausdrucks als Parameter an den Setter. In gewissem Sinne ist diese Methode für das „Festlegen“ des Eigenschaftswerts verantwortlich. Der Rückgabewert der Setter-Methode kann ignoriert werden.

Zum Beispiel:

var obj = {}, value = null;
Object.defineProperty(obj, "num", {
    get: function(){
        console.log('执行了 get 操作')
        return value;
    },
    set: function(newValue) {
        console.log('执行了 set 操作')
        value = newValue;
    }
})

obj.value = 1 // 执行了 set 操作

console.log(obj.value); // 执行了 get 操作 // 1
Nach dem Login kopieren

Ist das nicht die Art und Weise, wie wir Datenänderungen überwachen wollen? Fassen wir es noch einmal zusammen:

function Archiver() {
    var value = null;
    // archive n. 档案
    var archive = [];

    Object.defineProperty(this, 'num', {
        get: function() {
            console.log('执行了 get 操作')
            return value;
        },
        set: function(value) {
            console.log('执行了 set 操作')
            value = value;
            archive.push({ val: value });
        }
    });

    this.getArchive = function() { return archive; };
}

var arc = new Archiver();
arc.num; // 执行了 get 操作
arc.num = 11; // 执行了 set 操作
arc.num = 13; // 执行了 set 操作
console.log(arc.getArchive()); // [{ val: 11 }, { val: 13 }]
Nach dem Login kopieren

watch API

Da Datenänderungen überwacht werden können, kann ich mir vorstellen, dass bei Datenänderungen die Rendering-Arbeit automatisch ausgeführt wird. Beispiel:

Es gibt ein Span-Tag und ein Button-Tag in HTML

<span id="container">1</span>
<button id="button">点击加 1</button>
Nach dem Login kopieren

Wenn auf die Schaltfläche geklickt wird, wird der Wert im Span-Tag um 1 erhöht.

Der traditionelle Ansatz ist:

document.getElementById(&#39;button&#39;).addEventListener("click", function(){
    var container = document.getElementById("container");
    container.innerHTML = Number(container.innerHTML) + 1;
});
Nach dem Login kopieren

Wenn defineProperty verwendet wird:

var obj = {
    value: 1
}

// 储存 obj.value 的值
var value = 1;

Object.defineProperty(obj, "value", {
    get: function() {
        return value;
    },
    set: function(newValue) {
        value = newValue;
        document.getElementById(&#39;container&#39;).innerHTML = newValue;
    }
});

document.getElementById(&#39;button&#39;).addEventListener("click", function() {
    obj.value += 1;
});
Nach dem Login kopieren

Der Code scheint zu wachsen, aber wenn wir den Wert im Span-Tag direkt ändern müssen Ändern Sie einfach den Wert von obj.value.

Bei der aktuellen Schreibweise müssen wir jedoch immer noch eine separate Variable deklarieren, um den Wert von obj.value zu speichern, denn wenn Sie direkt obj.value = newValue in set eingeben, geraten Sie in eine Endlosschleife. Darüber hinaus müssen wir möglicherweise Änderungen in vielen Attributwerten überwachen. Es wäre ermüdend, sie einzeln zu schreiben, also schreiben wir einfach eine Überwachungsfunktion. Die Auswirkung der Verwendung ist wie folgt:

var obj = {
    value: 1
}

watch(obj, "num", function(newvalue){
    document.getElementById(&#39;container&#39;).innerHTML = newvalue;
})

document.getElementById(&#39;button&#39;).addEventListener("click", function(){
    obj.value += 1
});
Nach dem Login kopieren

Schreiben wir diese Überwachungsfunktion:

(function(){
    var root = this;
    function watch(obj, name, func){
        var value = obj[name];

        Object.defineProperty(obj, name, {
            get: function() {
                return value;
            },
            set: function(newValue) {
                value = newValue;
                func(value)
            }
        });

        if (value) obj[name] = value
    }

    this.watch = watch;
})()
Nach dem Login kopieren

Jetzt können wir Änderungen in Objektattributwerten überwachen und Rückruffunktionen basierend auf Änderungen in Attributwerten hinzufügen ~

Proxy

Die Verwendung von defineProperty kann nur das Leseverhalten (Get) und das Festlegen (Setzen) von Eigenschaften neu definieren. In ES6 wird Proxy bereitgestellt, und es können weitere Verhaltensweisen neu definiert werden in, löschen, Funktionsaufruf und weitere Verhaltensweisen.

Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。我们来看看它的语法:

var proxy = new Proxy(target, handler);
Nach dem Login kopieren

proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法。其中,new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。

var proxy = new Proxy({}, {
    get: function(obj, prop) {
        console.log(&#39;设置 get 操作&#39;)
        return obj[prop];
    },
    set: function(obj, prop, value) {
        console.log(&#39;设置 set 操作&#39;)
        obj[prop] = value;
    }
});

proxy.time = 35; // 设置 set 操作

console.log(proxy.time); // 设置 get 操作 // 35
Nach dem Login kopieren

除了 get 和 set 之外,proxy 可以拦截多达 13 种操作,比如 has(target, propKey),可以拦截 propKey in proxy 的操作,返回一个布尔值。

// 使用 has 方法隐藏某些属性,不被 in 运算符发现
var handler = {
  has (target, key) {
    if (key[0] === &#39;_&#39;) {
      return false;
    }
    return key in target;
  }
};
var target = { _prop: &#39;foo&#39;, prop: &#39;foo&#39; };
var proxy = new Proxy(target, handler);
console.log(&#39;_prop&#39; in proxy); // false
Nach dem Login kopieren

又比如说 apply 方法拦截函数的调用、call 和 apply 操作。

apply 方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组,不过这里我们简单演示一下:

var target = function () { return &#39;I am the target&#39;; };
var handler = {
  apply: function () {
    return &#39;I am the proxy&#39;;
  }
};

var p = new Proxy(target, handler);

p();
// "I am the proxy"
Nach dem Login kopieren

又比如说 ownKeys 方法可以拦截对象自身属性的读取操作。具体来说,拦截以下操作:

  • Object.getOwnPropertyNames()

  • Object.getOwnPropertySymbols()

  • Object.keys()

下面的例子是拦截第一个字符为下划线的属性名,不让它被 for of 遍历到。

let target = {
  _bar: &#39;foo&#39;,
  _prop: &#39;bar&#39;,
  prop: &#39;baz&#39;
};

let handler = {
  ownKeys (target) {
    return Reflect.ownKeys(target).filter(key => key[0] !== &#39;_&#39;);
  }
};

let proxy = new Proxy(target, handler);
for (let key of Object.keys(proxy)) {
  console.log(target[key]);
}
// "baz"
Nach dem Login kopieren

更多的拦截行为可以查看阮一峰老师的 《ECMAScript 6 入门》

值得注意的是,proxy 的最大问题在于浏览器支持度不够,而且很多效果无法使用 poilyfill 来弥补。

watch API 优化

我们使用 proxy 再来写一下 watch 函数。使用效果如下:

(function() {
    var root = this;

    function watch(target, func) {

        var proxy = new Proxy(target, {
            get: function(target, prop) {
                return target[prop];
            },
            set: function(target, prop, value) {
                target[prop] = value;
                func(prop, value);
            }
        });

        if(target[name]) proxy[name] = value;
        return proxy;
    }

    this.watch = watch;
})()

var obj = {
    value: 1
}

var newObj = watch(obj, function(key, newvalue) {
    if (key == &#39;value&#39;) document.getElementById(&#39;container&#39;).innerHTML = newvalue;
})

document.getElementById(&#39;button&#39;).addEventListener("click", function() {
    newObj.value += 1
});
Nach dem Login kopieren

我们也可以发现,使用 defineProperty 和 proxy 的区别,当使用 defineProperty,我们修改原来的 obj 对象就可以触发拦截,而使用 proxy,就必须修改代理对象,即 Proxy 的实例才可以触发拦截。

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in defineProperty und Proxy in ES6 (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
2 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Repo: Wie man Teamkollegen wiederbelebt
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Abenteuer: Wie man riesige Samen bekommt
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Tipps zum dynamischen Erstellen neuer Funktionen in Golang-Funktionen Tipps zum dynamischen Erstellen neuer Funktionen in Golang-Funktionen Apr 25, 2024 pm 02:39 PM

Die Go-Sprache bietet zwei Technologien zur dynamischen Funktionserstellung: Schließung und Reflexion. Abschlüsse ermöglichen den Zugriff auf Variablen innerhalb des Abschlussbereichs, und durch Reflektion können mithilfe der FuncOf-Funktion neue Funktionen erstellt werden. Diese Technologien sind nützlich bei der Anpassung von HTTP-Routern, der Implementierung hochgradig anpassbarer Systeme und dem Aufbau steckbarer Komponenten.

Überlegungen zur Parameterreihenfolge bei der Benennung von C++-Funktionen Überlegungen zur Parameterreihenfolge bei der Benennung von C++-Funktionen Apr 24, 2024 pm 04:21 PM

Bei der Benennung von C++-Funktionen ist es wichtig, die Reihenfolge der Parameter zu berücksichtigen, um die Lesbarkeit zu verbessern, Fehler zu reduzieren und das Refactoring zu erleichtern. Zu den gängigen Konventionen für die Parameterreihenfolge gehören: Aktion-Objekt, Objekt-Aktion, semantische Bedeutung und Einhaltung der Standardbibliothek. Die optimale Reihenfolge hängt vom Zweck der Funktion, den Parametertypen, möglichen Verwirrungen und Sprachkonventionen ab.

Wie schreibe ich effiziente und wartbare Funktionen in Java? Wie schreibe ich effiziente und wartbare Funktionen in Java? Apr 24, 2024 am 11:33 AM

Der Schlüssel zum Schreiben effizienter und wartbarer Java-Funktionen ist: Halten Sie es einfach. Verwenden Sie eine aussagekräftige Benennung. Bewältigen Sie besondere Situationen. Nutzen Sie entsprechende Sichtbarkeit.

Vollständige Sammlung von Excel-Funktionsformeln Vollständige Sammlung von Excel-Funktionsformeln May 07, 2024 pm 12:04 PM

1. Die SUMME-Funktion wird verwendet, um die Zahlen in einer Spalte oder einer Gruppe von Zellen zu summieren, zum Beispiel: =SUMME(A1:J10). 2. Die Funktion AVERAGE wird verwendet, um den Durchschnitt der Zahlen in einer Spalte oder einer Gruppe von Zellen zu berechnen, zum Beispiel: =AVERAGE(A1:A10). 3. COUNT-Funktion, die verwendet wird, um die Anzahl der Zahlen oder Texte in einer Spalte oder einer Gruppe von Zellen zu zählen, zum Beispiel: =COUNT(A1:A10) 4. IF-Funktion, die verwendet wird, um logische Urteile auf der Grundlage spezifizierter Bedingungen zu treffen und die zurückzugeben entsprechendes Ergebnis.

Vergleich der Vor- und Nachteile von C++-Funktionsstandardparametern und variablen Parametern Vergleich der Vor- und Nachteile von C++-Funktionsstandardparametern und variablen Parametern Apr 21, 2024 am 10:21 AM

Zu den Vorteilen von Standardparametern in C++-Funktionen gehören die Vereinfachung von Aufrufen, die Verbesserung der Lesbarkeit und die Vermeidung von Fehlern. Die Nachteile sind eingeschränkte Flexibilität und Namensbeschränkungen. Zu den Vorteilen variadischer Parameter gehören unbegrenzte Flexibilität und dynamische Bindung. Zu den Nachteilen gehören eine größere Komplexität, implizite Typkonvertierungen und Schwierigkeiten beim Debuggen.

Welche Vorteile haben C++-Funktionen, die Referenztypen zurückgeben? Welche Vorteile haben C++-Funktionen, die Referenztypen zurückgeben? Apr 20, 2024 pm 09:12 PM

Zu den Vorteilen von Funktionen, die Referenztypen in C++ zurückgeben, gehören: Leistungsverbesserungen: Durch die Übergabe als Referenz wird das Kopieren von Objekten vermieden, wodurch Speicher und Zeit gespart werden. Direkte Änderung: Der Aufrufer kann das zurückgegebene Referenzobjekt direkt ändern, ohne es neu zuzuweisen. Einfachheit des Codes: Die Übergabe als Referenz vereinfacht den Code und erfordert keine zusätzlichen Zuweisungsvorgänge.

Erweiterte Verwendung von Referenzparametern und Zeigerparametern in C++-Funktionen Erweiterte Verwendung von Referenzparametern und Zeigerparametern in C++-Funktionen Apr 21, 2024 am 09:39 AM

Referenzparameter in C++-Funktionen (im Wesentlichen Variablenaliase; durch Ändern der Referenz wird die Originalvariable geändert) und Zeigerparameter (Speichern der Speicheradresse der Originalvariablen, Ändern der Variablen durch Dereferenzierung des Zeigers) werden beim Übergeben und Ändern von Variablen unterschiedlich verwendet. Referenzparameter werden oft verwendet, um Originalvariablen (insbesondere große Strukturen) zu ändern, um Kopieraufwand bei der Übergabe an Konstruktoren oder Zuweisungsoperatoren zu vermeiden. Zeigerparameter werden verwendet, um flexibel auf Speicherorte zu zeigen, dynamische Datenstrukturen zu implementieren oder Nullzeiger zur Darstellung optionaler Parameter zu übergeben.

Was ist der Unterschied zwischen benutzerdefinierten PHP-Funktionen und vordefinierten Funktionen? Was ist der Unterschied zwischen benutzerdefinierten PHP-Funktionen und vordefinierten Funktionen? Apr 22, 2024 pm 02:21 PM

Der Unterschied zwischen benutzerdefinierten PHP-Funktionen und vordefinierten Funktionen ist: Umfang: Benutzerdefinierte Funktionen sind auf den Umfang ihrer Definition beschränkt, während auf vordefinierte Funktionen im gesamten Skript zugegriffen werden kann. So definieren Sie: Benutzerdefinierte Funktionen werden mit dem Schlüsselwort function definiert, während vordefinierte Funktionen vom PHP-Kernel definiert werden. Parameterübergabe: Benutzerdefinierte Funktionen empfangen Parameter, während vordefinierte Funktionen möglicherweise keine Parameter erfordern. Erweiterbarkeit: Benutzerdefinierte Funktionen können nach Bedarf erstellt werden, während vordefinierte Funktionen integriert sind und nicht geändert werden können.

See all articles