Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung der grundlegenden JavaScript-Objekte (organisiert und gemeinsam genutzt)

Detaillierte Erläuterung der grundlegenden JavaScript-Objekte (organisiert und gemeinsam genutzt)

WBOY
WBOYnach vorne
2021-12-20 15:06:542049Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Objekte in JavaScript. Objekte in JavaScript sind ebenfalls Variablen, aber Objekte enthalten viele Werte. Ich hoffe, dass er Ihnen nach dem Lesen dieses Artikels hilfreich sein wird. 1. Die Basis von Objekten 1.1 Typen null; der primitive Typ selbst ist kein Objekt.

Detaillierte Erläuterung der grundlegenden JavaScript-Objekte (organisiert und gemeinsam genutzt)null

Aber

null

wird manchmal als Objekt betrachtet, und der Typ null gibt ein Objekt zurück. Tatsächlich ist null ein Basistyp. Der Grund dafür ist, dass verschiedene Objekte auf der untersten Ebene als binär dargestellt werden. Wenn in JavaScript die ersten drei Ziffern der Binärdatei

0

sind, wird sie als Objekttyp beurteilt, und null bedeutet, dass alles 0 ist, sodass „typeof“ ein Objekt zurückgibt.

Spezielle Objektuntertypen

Arrays

Arrays sind ebenfalls ein Objekttyp mit einigen zusätzlichen Verhaltensweisen. Die Organisation von Arrays ist komplexer als bei gewöhnlichen Objekten.

Funktion

Funktion ist im Wesentlichen dasselbe wie eine gewöhnliche Funktion, außer dass sie aufgerufen werden kann, sodass Sie Funktionen wie Objekte bedienen können. 1.2 Eingebautes Objekt

String

Zahl

Datum

Boolescher Wert

Objekt

Funktion

Array

1.3 Inhalt

.a heißt Attributzugriff, [‘a’] heißt Operatorzugriff.

//对象中的属性名始终是字符串
myobj={}

myobj[myobj]='bar'//赋值

myobj['[object object]'] //'bar'

1.4 Name des berechenbaren Attributs

es6 Name des berechenbaren Attributs hinzugefügt, Sie können [] in Textform verwenden, um einen Ausdruck als Attributnamen zu umschließen

var perfix = 'foo'

var myobj={
    [perfix + 'bar'] :'hello'
}

myobj['foobar']//hello

1.5 Attributdeskriptor

Ab es5 haben alle Attribute das Attribut „Mit“. Mit dem Deskriptor können Sie beispielsweise direkt bestimmen, ob das Attribut lesbar oder beschreibbar ist.
/*
 * 重要函数:
 * Object.getOwnPropertyDescriptor(..) //获取属性描述符
 * Object.defineProperty(..) //设置属性描述符
 */
 writeble(可读性)
 configurable(可配置性)
 enumerable (可枚举性)

1.6 Traversal

for in

for in kann verwendet werden, um die aufzählbare Attributliste eines Objekts (einschließlich der [[Prototype]]-Kette zu durchlaufen), und Sie müssen den Attributwert manuell abrufen. Kann Arrays und gewöhnliche Objekte durchlaufen.

for of

es6 ist neu und kann zum Durchlaufen der Attributwerte von Arrays verwendet werden. Die for of-Schleife fordert zuerst ein Iteratorobjekt vom Objekt an, auf das zugegriffen wird, und ruft es dann auf (des Iteratorobjekts) Methode zum Durchlaufen aller Rückgabewerte.

Arrays verfügen über integrierte @@-Iteratoren.

Wie funktioniert das?

var arr = [1, 2, 3]
var it = arr[Symbol.iterator]()//迭代器对象
console.log(it.next());//{value: 1, done: false}
console.log(it.next());//{value: 2, done: false}
console.log(it.next());//{value: 3, done: false}
console.log(it.next());//{value: undefined, done: true}

/*
 * 用es6 的Symbol.iterator 来获取对象的迭代器内部属性。
 * @@iterator本身并不是一个迭代器对象,而是一个返回迭代器对象的函数。
 */

Wie verfügt ein Objekt über einen integrierten @@iterator, um die Werte von Attributen zu durchlaufen?

Da das Objekt keinen integrierten @@iterator hat, kann die for...of-Durchquerung nicht automatisch abgeschlossen werden. Sie können jedoch @@iterator für jedes Objekt definieren, das Sie durchlaufen möchten, zum Beispiel:

  var obj={
      a:1,b:2
  }
  
   Object.defineProperty(obj, Symbol.iterator, {
        enumerable: false,
        writable: false,
        configurable: true,
        value: function () {
            var self = this
            var idx = 0
            var ks = Object.keys(self)
            return {
                next: function () {
                    return {
                        value: self[ks[idx++]],
                        done: (idx > ks.length)
                    }
                }
            }
        }
    })
    
    //手动遍历
    var it = obj[Symbol.iterator]()//迭代器对象
    console.log(it.next());//{value: 1, done: false}
    console.log(it.next());//{value: 2, done: false}
    console.log(it.next());//{value: undefined, done: true}

   //for of 遍历
    for (const v of obj) {
        console.log(v);
    }
    //2
    //3

Andere Array-Traversalfunktionen

 /*
 forEach:会遍历所有并忽略返回值
 some:会一直运行到回调函数返回 true(或者"真"值)
 every:会一直运行到回调函数返回 false(或者"假"值)
 map:
 filter:返回满足条件的值
 reduce:
 some和every 和for的break语句类似,会提前终止遍历
 */

2. Interviewfragen

1
Verwandte Kenntnisse

Grundtypen und Referenztypen

Wie oben erwähnt, gibt es in JavaScript sechs Hauptsprachentypen: Zeichenfolge, Zahl, Boolescher Wert, Null, Undefiniert und Objekt Referenztyp.

Die Speichermethoden von JavaScript-Variablen: Stapel und Heap

Stack: Speichert automatisch Speicherplatz zu und wird vom System automatisch freigegeben. Es speichert grundlegende Typwerte und Referenztypadressen variabel und wird nicht automatisch freigegeben. Darin werden Referenztypwerte gespeichert

Der größte Unterschied zwischen Basistypen und Referenztypen ist der Unterschied zwischen der Wertübergabe und der Adressübergabe

Basistypen verwenden die Wertübergabe; Referenztypen verwenden die Adressübergabe (Zeiger). Speichern Sie die Adresse im Stapelspeicher. Weisen Sie der empfangenen Variablen einen Wert zu.

Was sind Shallow Copy und Deep Copy?

Flache Kopie

: Eine flache Kopie eines Objekts kopiert das „Hauptobjekt“, jedoch nicht die Objekte innerhalb des Objekts. Das „innere Objekt“ wird vom Originalobjekt und seiner Kopie gemeinsam genutzt.

Tiefe Kopie

: Eine tiefe Kopie eines Objekts kopiert nicht nur jedes Attribut des ursprünglichen Objekts einzeln, sondern kopiert mithilfe der tiefen Kopie auch rekursiv die in jedem Attribut des ursprünglichen Objekts enthaltenen Objekte in das neue Objekt Methode, sodass Änderungen an einem Objekt keine Auswirkungen auf das andere Objekt haben.


Zum Beispiel:

var anotherObject={
    b:"b"
}

var anotherArray=[]

var myObject={
    a:'a',
    b:anotherObject, //引用,不是副本
    c:anotherArray //另外一个引用
}

anotherArray.push(anotherObject,myObject)

/*
  如何准确的复制 myObject?
 浅复制 myObject,就是复制出 新对象中的 a 的值会复制出对象中a 的值,也就是 'a',
 但是对象中的 b、c两个属性其实只是三个引用,新对象的b、c属性和旧对象的是一样的。
 
 深复制 myObject,除了复制 myObject 以外还会复制 anotherObject 和 anotherArray。
 但是这里深复制 myObject会出现一个问题,anotherArray 引用 anotherObject 和 myObject,
 所以又需要复制 myObject,这样就会由于循环引用导致死循环。
 后面会介绍如何处理这种情况。
*/
So implementieren Sie eine flache Kopie

object

object.assign(), Spread-Operator (...)

var obj1 = {x: 1, y: 2}
var obj2 = Object.assign({}, obj1);
console.log(obj1) //{x: 1, y: 2}
console.log(obj2) //{x: 1, y: 2}
obj2.x = 2; //修改obj2.x
console.log(obj1) //{x: 1, y: 2}
console.log(obj2) //{x: 2, y: 2}

var obj1 = {
    x: 1, 
    y: {
        m: 1
    }
};
var obj2 = Object.assign({}, obj1);
console.log(obj1) //{x: 1, y: {m: 1}}
console.log(obj2) //{x: 1, y: {m: 1}}
obj2.y.m = 2; //修改obj2.y.m
console.log(obj1) //{x: 1, y: {m: 2}}
console.log(obj2) //{x: 2, y: {m: 2}}

Array

slice(), concat, Array.from(), spread Operatorsymbol (...), concat, for-Schleife

var arr1 = [1, 2, [3, 4]], arr2 = arr1.slice();
console.log(arr1); //[1, 2, [3, 4]]
console.log(arr2); //[1, 2, [3, 4]]

arr2[0] = 2 
arr2[2][1] = 5; 
console.log(arr1); //[1, 2, [3, 5]]
console.log(arr2); //[2, 2, [3, 5]]

So implementieren Sie Deep Copy

JSON.parse(JSON.stringify(obj))Während des Serialisierungsprozesses von JSON.stringify() undefinierte, beliebige Funktionen und Symbole Werte werden während der Serialisierung ignoriert (beim Erscheinen in Eigenschaftswerten von Nicht-Array-Objekten) oder in Null konvertiert (beim Erscheinen in Arrays).

var obj1 = {
    x: 1, 
    y: {
        m: 1
    },
    a:undefined,
    b:function(a,b){
      return a+b
    },
    c:Symbol("foo")
};
var obj2 = JSON.parse(JSON.stringify(obj1));

console.log(obj1) //{x: 1, y: {m: 1}, a: undefined, b: ƒ, c: Symbol(foo)}
console.log(obj2) //{x: 1, y: {m: 1}}
obj2.y.m = 2; //修改obj2.y.m
console.log(obj1) //{x: 1, y: {m: 1}, a: undefined, b: ƒ, c: Symbol(foo)}
console.log(obj2) //{x: 2, y: {m: 2}}

Einfache Implementierung der Deep-Copy-Funktion
function deepClone(obj){
  let result = Array.isArray(obj)?[]:{};
  if(obj && typeof obj === "object"){
    for(let key in obj){
      if(obj.hasOwnProperty(key)){
        if(obj[key] && typeof obj[key] === "object"){
          result[key] = deepClone(obj[key]);
        }else{
          result[key] = obj[key];
        }
      }
    }
  }
  return result;
}

var obj1 = {
    x: {
        m: 1
    },
    y: undefined,
    z: function add(z1, z2) {
        return z1 + z2
    },
    a: Symbol("foo"),
    b: [1,2,3,4,5],
    c: null
};
var obj2 = deepClone(obj1);
obj2.x.m = 2;
obj2.b[0] = 2;
console.log(obj1);
console.log(obj2);

//obj1
{
a: Symbol(foo)
b: (5) [1, 2, 3, 4, 5]
c: null
x: {m: 1}
y: undefined
z: ƒ add(z1, z2)
}

//obj2
{
a: Symbol(foo)
b: (5) [2, 2, 3, 4, 5]
c: null
x: {m: 2}
y: undefined
z: ƒ add(z1, z2)
}

Die obige Deep-Copy-Methode stößt auf einen Zirkelverweis und gerät in einen zyklischen rekursiven Prozess, wodurch der Stapel explodiert. Daher sind Verbesserungen erforderlich.

Verbesserung der Deep-Copy-Funktion (Verhinderung einer Schleifenrekursion)

Um das Problem der Stapelexplosion aufgrund einer Schleifenrekursion zu lösen, müssen Sie nur bestimmen, ob sich das Feld eines Objekts auf dieses Objekt oder ein übergeordnetes Objekt dieses Objekts bezieht.

function deepClone(obj, parent = null){ // 改进(1)
  let result = Array.isArray(obj)?[]:{};
  let _parent = parent;  // 改进(2)
  while(_parent){ // 改进(3)
    if(_parent.originalParent === obj){
      return _parent.currentParent;
    }
    _parent = _parent.parent;
  }
  if(obj && typeof obj === "object"){
    for(let key in obj){
      if(obj.hasOwnProperty(key)){
        if(obj[key] && typeof obj[key] === "object"){
          result[key] = deepClone(obj[key],{ // 改进(4)
            originalParent: obj,
            currentParent: result,
            parent: parent
          });
        }else{
          result[key] = obj[key];
        }
      }
    }
  }
  return result;
}

// 调试用
var obj1 = {
    x: 1, 
    y: 2
};
obj1.z = obj1;
var obj2 = deepClone(obj1);
console.log(obj1); 
console.log(obj2);

Die endgültige Version der Deep Copy-Funktion (unterstützt grundlegende Datentypen, Prototypketten, RegExp, Datumstypen)

function deepClone(obj, parent = null){ 
  let result; // 最后的返回结果

  let _parent = parent; // 防止循环引用
  while(_parent){
    if(_parent.originalParent === obj){
      return _parent.currentParent;
    }
    _parent = _parent.parent;
  }
  
  if(obj && typeof obj === "object"){ // 返回引用数据类型(null已被判断条件排除))
    if(obj instanceof RegExp){ // RegExp类型
      result = new RegExp(obj.source, obj.flags)
    }else if(obj instanceof Date){ // Date类型
      result = new Date(obj.getTime());
    }else{
      if(obj instanceof Array){ // Array类型
        result = []
      }else{ // Object类型,继承原型链
        let proto = Object.getPrototypeOf(obj);
        result = Object.create(proto);
      }
      for(let key in obj){ // Array类型 与 Object类型 的深拷贝
        if(obj.hasOwnProperty(key)){
          if(obj[key] && typeof obj[key] === "object"){
            result[key] = deepClone(obj[key],{ 
              originalParent: obj,
              currentParent: result,
              parent: parent
            });
          }else{
            result[key] = obj[key];
          }
        }
      }
    }
  }else{ // 返回基本数据类型与Function类型,因为Function不需要深拷贝
    return obj
  }
  return result;
}

// 调试用
function construct(){
    this.a = 1,
    this.b = {
        x:2,
        y:3,
        z:[4,5,[6]]
    },
    this.c = [7,8,[9,10]],
    this.d = new Date(),
    this.e = /abc/ig,
    this.f = function(a,b){
        return a+b
    },
    this.g = null,
    this.h = undefined,
    this.i = "hello",
    this.j = Symbol("foo")
}
construct.prototype.str = "I'm prototype"
var obj1 = new construct()
obj1.k = obj1
obj2 = deepClone(obj1)
obj2.b.x = 999
obj2.c[0] = 666
console.log(obj1)
console.log(obj2)
console.log(obj1.str)
console.log(obj2.str)

Hinweis: Deep Copy des Funktionstyps:

bind(): Verwenden Sie fn.bind(), um eine tiefe Kopie der Funktion zu erstellen, diese kann jedoch aufgrund des Problems dieses Zeigers nicht verwendet werden.

eval(fn.toString()): Unterstützt nur normale Pfeilfunktionen Funktion function fn() {} ist nicht anwendbar;

new Function(arg1, arg2,…,function_body): Die Parameter und der Funktionskörper müssen extrahiert werden

PS: Im Allgemeinen besteht keine Notwendigkeit, die Funktion tief zu kopieren.

【Verwandte Empfehlungen: Javascript-Lern-Tutorial

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der grundlegenden JavaScript-Objekte (organisiert und gemeinsam genutzt). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen