Bevor wir Configurable
erklären, werfen wir zunächst einen Blick auf eine Interviewfrage:
a = 1; console.log( window.a ); // 1 console.log( delete window.a ); // true console.log( window.a ); // undefined var b = 2; console.log( window.b ); // 2 console.log( delete window.b ); // false console.log( window.b ); // 2
Aus der obigen Frage können wir zwei Unterschiede erkennen: Wenn eine Variable nicht mit var deklariert wird, kann sie mit dem Schlüsselwort delete gelöscht werden, und der Wert ist undefiniert, wenn er erneut abgerufen wird, wenn eine Variable mit var deklariert wird. Es kann nicht mit delete gelöscht werden und der Wert ist beim Abrufen immer noch 2.
Wenn Sie delete verwenden, um eine Variable oder ein Attribut zu löschen, wird „true“ zurückgegeben, wenn der Löschvorgang erfolgreich ist, andernfalls wird „false“ zurückgegeben. Wenn delete wie im obigen Beispiel die Variable a nicht löschen kann, wird false zurückgegeben. Wenn delete die Variable b erfolgreich löschen kann, wird true zurückgegeben.
Zusätzlich zu den beiden oben genannten Situationen gibt es verschiedene andere häufig verwendete Variablen, die durch Löschen gelöscht werden können, und einige, die nicht gelöscht werden können. Machen wir uns keine Gedanken darüber, warum delete zu einem solchen Ergebnis führt. Hier betrachten wir nur den Rückgabewert:
Ein Element im Löscharray löschen:
// 使用for~in是循环不到的,直接忽略到该元素 // 使用for()可以得到该元素,但是值是undefined var arr = [1, 2, 3, 4]; console.log( arr ); // [1, 2, 3, 4] console.log( delete arr[2] ); // true,删除成功 console.log( arr ); // [1, 2, undefined, 4]
Funktionstypvariablen löschen:
// chrome 不能删除;火狐可以删除 function func(){ } console.log( func ); console.log( delete func ); console.log( func );
Löschen Sie function.length, das ist die Anzahl der erhaltenen formalen Parameter:
function func1(a, b){ } console.log( func1.length ); // 2 console.log( delete func1.length ); // true,删除成功 console.log( func1.length ); // 0
Häufig verwendete Variablen löschen:
console.log( delete NaN ); // false,删除失败 console.log( delete undefined );// false console.log( delete Infinity ); // false console.log( delete null ); // true,删除成功
Löschen Sie den Prototyp, anstatt die Attribute auf dem Prototyp zu löschen:
function Person(){ } Person.prototype.name = "蚊子"; console.log( delete Person.prototype ); // false,无法删除 console.log( delete Object.prototype ); // false
Beim Löschen der Länge von Arrays und Strings:
var arr = [1, 2, 3, 4]; console.log( arr.length ); // 4 console.log( delete arr.length ); // false,删除失败 console.log( arr.length ); // 4 var str = 'abcdefg'; console.log( str.length ); // 7 console.log( delete str.length ); // false,删除失败 console.log( str.length ); // 7
Beim Löschen von Attributen in obj:
var obj = {name:'wenzi', age:25}; console.log( obj.name ); // wenzi console.log( delete obj.name ); // true,删除成功 console.log( obj.name ); // undefined console.log( obj ); // { age:25 }
Wenn Sie Attribute in einem Instanzobjekt löschen, können Sie der folgenden Ausgabe entnehmen, dass beim Löschen von Attributen nur die Attribute des Instanzobjekts selbst gelöscht werden und die Attribute im Prototyp nicht gelöscht werden können Wenn Sie es erneut löschen, wird es weiterhin gelöscht. Wenn Sie die Attribute oder Methoden der Attribute auf dem Prototyp löschen möchten, können Sie sie nur löschen: delete Person.prototype.name
:
function Person(){ this.name = 'wenzi'; } Person.prototype.name = '蚊子'; var student = new Person(); console.log( student.name ); // wenzi console.log( delete student.name ); // true,删除成功 console.log( student.name ); // 蚊子 console.log( delete student.name ); // true console.log( student.name ); // 蚊子 console.log( delete Person.prototype.name );// true,删除成功 console.log( student.name ); // undefined
Im obigen Beispiel können einige Variablen oder Attribute erfolgreich gelöscht werden, während andere nicht gelöscht werden können. Was bestimmt also, ob diese Variable oder dieses Attribut gelöscht werden kann?
ECMA-262 5. Edition definiert die Eigenschaften von JS-Objekteigenschaften (wird in JS-Engines verwendet, nicht direkt von außen zugänglich). In ECMAScript gibt es zwei Arten von Eigenschaften: Dateneigenschaften und Zugriffseigenschaften.
Ein Datenattribut bezieht sich auf einen Ort, der einen Datenwert enthält, an dem der Wert gelesen oder geschrieben werden kann. Dieses Attribut verfügt über 4 Eigenschaften, die sein Verhalten beschreiben:
Um die Standardeigenschaften von Objekteigenschaften zu ändern (die Standardeinstellung ist true), können Sie die Methode Object.defineProperty() aufrufen, die drei Parameter empfängt: das Objekt, in dem sich die Eigenschaft befindet, den Eigenschaftsnamen und ein Deskriptorobjekt ( muss sein: konfigurierbar, nummerierbar, beschreibbar und Wert, ein oder mehrere Werte können festgelegt werden).
lautet wie folgt:
var person = {}; Object.defineProperty(person, 'name', { configurable: false, // 不可删除,且不能修改为访问器属性 writable: false, // 不可修改 value: 'wenzi' // name的值为wenzi }); console.log( person.name); // wenzi console.log( delete person.name ); // false,无法删除 person.name = 'lily'; console.log( person.name ); // wenzi
Es ist ersichtlich, dass der Wert von person.name weder gelöscht noch zurückgesetzt wird. Dies liegt daran, dass der Aufruf der Funktion „defineProperty“ die Eigenschaften der Objekteigenschaften ändert. Es ist erwähnenswert, dass „defineProperty“ dies kann, sobald „configurable“ auf „false“ gesetzt ist nicht mehr zum Ändern der Eigenschaften des Objekts verwendet werden. Ändern Sie es auf „true“ (die Ausführung meldet einen Fehler: Uncaught TypeError: Cannot redefine property: name);
Es enthält hauptsächlich ein Paar Getter- und Setter-Funktionen. Beim Lesen des Accessor-Attributs wird der Getter aufgerufen, um einen gültigen Wert zurückzugeben. Wenn das Accessor-Attribut geschrieben wird, wird der Setter aufgerufen Attribut hat die folgenden 4 Eigenschaften:
var person = { _age: 18 }; Object.defineProperty(person, 'isAdult', { Configurable : false, get: function () { if (this._age >= 18) { return true; } else { return false; } } }); console.log( person.isAdult ); // true
Wenn sie wie folgt definiert sind, existieren Zugriffseigenschaften und Dateneigenschaften gleichzeitig:
上面的代码看起来貌似是没有什么问题,但是真正执行时会报错,报错如下:
Uncaught TypeError: Invalid property. A property cannot both have accessors and be writable or have a value
对于数据属性,可以取得:configurable,enumberable,writable和value;
对于访问器属性,可以取得:configurable,enumberable,get和set。
由此我们可知:一个变量或属性是否可以被删除,是由其内部属性Configurable
进行控制的,若Configurable
为true,则该变量或属性可以被删除,否则不能被删除。
可是我们应该怎么获取这个Configurable
值呢,总不能用delete试试能不能删除吧。有办法滴!!
ES5为我们提供了Object.getOwnPropertyDescriptor(object, property)
来获取内部属性。
如:
var person = {name:'wenzi'}; var desp = Object.getOwnPropertyDescriptor(person, 'name'); // person中的name属性 console.log( desp ); // {value: "wenzi", writable: true, enumerable: true, configurable: true}
通过Object.getOwnPropertyDescriptor(object, property)
我们能够获取到4个内部属性,configurable控制着变量或属性是否可被删除。这个例子中,person.name的configurable是true,则说明是可以被删除的:
console.log( person.name ); // wenzi console.log( delete person.name ); // true,删除成功 console.log( person.name ); // undefined
我们再回到最开始的那个面试题:
a = 1; var desp = Object.getOwnPropertyDescriptor(window, 'a'); console.log( desp.configurable ); // true,可以删除 var b = 2; var desp = Object.getOwnPropertyDescriptor(window, 'b'); console.log( desp.configurable ); // false,不能删除
跟我们使用delete操作删除变量时产生的结果是一样的。
别看一个简简单单的delete操作,里面其实包含了很多的原理!