Heim >Web-Frontend >js-Tutorial >Detaillierte Erläuterung der Objekteigenschaften in JavaScript
Das Konzept von Objekten in JavaScript kann wirklich verwirrend sein. Schauen Sie sich das folgende Beispiel an:
var strPrimitive = "I'm mamacat"; typeof strPrimitive; // "string" strPrimitive instanceof String; // false var strObject = new String("I'm mamacat"); typeof strObject; // "object" strObject instanceof String; // true strPrimitive.substr(8, 3); // "cat"
Manchmal ist es ein String-Typ und manchmal ein Objekt. Allerdings können Variablen, die offensichtlich keine Objekttypen sind, trotzdem Objektattribute verwenden. Warum ist das so?
[Verwandte Kursempfehlungen: JavaScript-Video-Tutorial]
Typen und integrierte Objekte
Es gibt sechs Haupttypen in JavaScript (Sprache) Typen, nämlich string, number, boolean, null, undefiniert und object, wobei die ersten fünf Grundtypen keine Objekte sind (Typisierung null führt zu „object“, was die Sprache selbst ist INSEKT). Darüber hinaus gibt es viele spezielle Objektuntertypen wie Arrays, Funktionen und integrierte Objekte.
Die Namen einiger integrierter Objekte sehen genauso aus wie einfache Grundtypen, z. B. String, Boolean, Object usw. In Bezug auf den Ausdruck ähneln diese integrierten Objekte dem Konzept der „Klasse“ in anderen objektorientierten Sprachen. Wie im vorherigen Artikel erwähnt, handelt es sich tatsächlich nur um einige integrierte Funktionen, die zum Erstellen einer entsprechenden Funktion verwendet werden können Subtyp (nicht verwechseln, Funktionen sind auch Objekte, hier gibt es keinen Widerspruch). Wir können also zum ursprünglichen Beispiel zurückkehren. strObject ist eine Variable, die durch die integrierte Funktion/das integrierte Objekt String erstellt wird und dem String-Subtyp entspricht. Es handelt sich also um ein Objekt, und strPrimitive ist nur ein primitiver Literalwert.
Natürlich scheinen wir am Ende des obigen Beispiels die Funktion substr() auf strPrimitive aufgerufen zu haben. Dies liegt daran, dass die JavaScript-Engine das ursprüngliche Literal bei Bedarf und danach in das entsprechende Objekt konvertiert die Konvertierung Wir können natürlich Attribute verwenden, um auf die entsprechenden Methoden zuzugreifen.
Objekteigenschaften
Für das obige Beispiel steht also für die String-Objektinstanz die Funktion substr() zur Verfügung, aber gemäß dem vorherigen Artikel können wir es wissen dass diese „Funktionen“ selbst nicht zu einem Objekt gehören, sondern dass diese Funktionen im Wesentlichen ein Attribut des entsprechenden Objekts sind. Selbst wenn wir sagen, dass ein bestimmter Objekttyp selbst verschiedene Attribute hat, existieren diese Attribute tatsächlich größtenteils unabhängig voneinander, stehen aber nur in Form von Referenzen im Widerspruch zu dem, was wir zuvor gelernt haben. Diese verwandten Dinge werden Eigenschaften des Objekts genannt.
Kopieren von Objekten
Kurzbericht einfügen Obwohl im vorherigen Artikel erwähnt, wurde oben wiederholt betont, dass es sich bei Attributen nur um unabhängige Einheiten handelt, die im Zusammenhang stehen Ja, manchmal gehen wir immer noch davon aus, dass Attribute Teil des Objekts sind, und das Kopieren von Objekten ist einer der einfachsten Orte, an denen man in Schwierigkeiten geraten kann. Wenn Sie sorgfältig darüber nachdenken, werden Sie wissen, dass beim Kopieren eines Objekts die im „kopierten“ Objekt enthaltenen Attributreferenzen tatsächlich auf denselben Ort verweisen wie die Attributreferenzen des ursprünglichen Objekts, da seine Attribute selbst nur Referenzassoziationen sind :
var ori = { a : 1}; var ori_copy = ori; ori.a = 61; ori_copy.a; // 61
Natürlich kann dies von unseren Erwartungen abweichen, und wenn wir das Objekt wirklich kopieren möchten, gibt es keine perfekt anwendbare Lösung. In vielen Fällen besteht die gängige Praxis darin, das Objekt zu serialisieren und dann zu deserialisieren . Holen Sie sich ein neues Objekt, um das Objekt zu kopieren (z. B. mit JSON). ES6 hat Object.assign()
hinzugefügt, um eine flache Kopie eines Objekts durchzuführen, indem alle aufzählbaren Eigenschaften des Objekts dem neuen Objekt zugewiesen werden. Allerdings ist zu beachten, dass die Gleichheitszeichenzuweisung nicht die Metainformation des Attributs (Attributdeskriptor, später beschrieben) zuordnet, sodass Sie gegebenenfalls besonderes Augenmerk darauf legen sollten.
Attributzugriff und Array
Der Zugriff auf die mit dem Objekt verknüpften Eigenschaften erfolgt über den Operator . oder [], obj.a und obj["a" ] Die Attribute, auf die zugegriffen wird, sind im Wesentlichen gleich, und der einzige Unterschied zwischen diesen beiden Zugriffsformen besteht darin, ob die Namen der Attribute, auf die zugegriffen wird, seltsame Symbole enthalten können. Was im []-Operator geworfen wird, ist eine Zeichenfolge. Tatsächlich ist der Attributname immer eine Zeichenfolge. Das Überraschende an diesem Konzept ist natürlich, dass der Indexzugriff auf Arrays keine Ausnahme darstellt, bevor Zahlen verwendet werden.
// 对象的属性访问: var tejilang = {1 : "Teji Wolf"}; tejilang instanceof Array; // false tejilang["1"]; // "Teji Wolf" tejilang[1]; // "Teji Wolf" // 这回保证它是 Array var macat = ["codingcat"]; macat instanceof Array; // true macat.length; // 1 macat[0]; // "codingcat" macat["0"]; // "codingcat" macat.length = 20; macat; // (20) ["codingcat", empty × 19]
数组下标既然不属例外情况,那数组对象必然有其它属性控制数组本身的行为,例如上例中,macat 数组的长度就是 length 属性所体现的,通过修改它的值也就改变了对象本身对外的表现形式。当然,由于数组本身就是对象,所以我们还是可以把数组当键值对来用,只是这种做法通常是没有意义且会让人感到困惑的。JavaScript 引擎通常都根据对象的类型做了不同程度的优化,故除了代码逻辑可读性外,合理的使用也是多少可以改善性能的。
能够通过字符访问属性还是存在一些别的好处的,比如 ES6 的可计算属性名。当然 ES6 不在本文的关注范围内,所以这里就不再讨论了。
属性描述符
有时我们可能不希望某个属性被随意修改,有时候我们需要额外配置一些属性的信息,自 ES5 起,所有的属性就都具备了“属性描述符”(Property Descriptor)来控制属性本身的这些元信息。
数据描述符
来看这个例子:
var chris = {}; Object.defineProperty(chris, "IQ", { value: 228, writable: false, configurable: true, enumerable: true }); chris.IQ = 61; // 静默失败了,如果是严格模式则会 TypeError chris.IQ; // 228
通过 defineProperty 可以对一个对象的属性配置其对应的属性描述符(元信息),而属性描述符则包含访问描述符和数据描述符,上面的例子中,defineProperty 的第三个参数就定义了数据的若干数据描述符,其中 writable 表示可写,configurable 表示属性是否可配置(注意,修改成不可配置是单向操作),enumerable 则表示属性是否应当出现在枚举中,比如 for..in 中。
显然我们可以通过属性描述符实现对属性的保护,而同时也存在一些方便函数来做近似的事。如 Object.preventExtensions() 会保留原有属性但禁止添加新属性,Object.seal() 会密封对象,在禁止添加新属性的基础上把原有属性标记为不可配置,Object.freeze() 会冻结对象,即在密封的基础上把数据访问属性标记为不可写。
[[Get]], [[Put]] 和访问描述符
在我们访问和赋值一个对象的属性时,实际上是通过 [[Get]] 和 [[Put]] 操作进行的,例如属性访问时,[[Get]] 会先找有没有这个属性,如果没有则会遍历对象的 [[Prototype]] 链(原型链,这次不谈这个概念)来找,实在找不到则返回 undefined 。而这个行为实际是允许我们通过设置 getter (get())和 setter (set())函数来改变的,它们被称为 访问描述符。
当我们提供访问描述符时,对应的访问操作就不再受到 value 和 writable 属性的影响了,另外需要注意的是,尽管它们也是属性描述符,但定义 getter 和 setter 并不要求一定要通过 defineProperty 设置:
var obj = { get a() { // 给 a 属性定义 getter return this._a_; }, set a(val) { // a 属性的 setter this._a_ = val * 2; } } obj.a = 2; obj.a; // 4
属性存在性
因为属性的值也可能是 undefined,不存在的属性直接访问得到的也是 undefined,所以直接通过简单的属性访问是无法区分是否存在的,这时我们即可通过 in 或者 hasOwnProperty() 检查属性是否存在对象中了:
var obj = {a : 2}; "a" in obj; // true obj.hasOwnProperty("a"); // true
尽管仍没有讲到原型链的概念,这里仍然应注意,in 操作符会检查原型链中是否存在属性,而 hasOwnProperty 则不会。另外在一些情况下,有的对象会没有 hasOwnProperty 这个属性(此处不提原因),这时可以用过 Object.prototype.hasOwnProperty.call(objName, propertyName) 来实现检查。
本文来自 js教程 栏目,欢迎学习!
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Objekteigenschaften in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!