Heim  >  Artikel  >  Web-Frontend  >  Teilen von Fragen zum Grundwissen von JavaScript-Interviews

Teilen von Fragen zum Grundwissen von JavaScript-Interviews

小云云
小云云Original
2018-02-12 15:21:543261Durchsuche

Teilen von Fragen zum Grundwissen von JavaScript-Interviews

Laut StackOverflow-Umfrage ist JavaScript seit 2014 die beliebteste Programmiersprache. Das ist natürlich sinnvoll, schließlich erfordert 1/3 der Entwicklungsarbeit einige JavaScript-Kenntnisse. Wenn Sie Entwickler werden möchten, sollten Sie daher diese Sprache lernen.

Der Hauptzweck dieses Blogs besteht darin, gemeinsame Konzepte in allen Interviews zusammenzufassen, damit Sie sie schnell verstehen können. (Angesichts der Tatsache, dass dieser Artikel zu lang ist, um das Lesen zu erleichtern, wird er zur Übersetzung in drei Blogs unterteilt. Dies ist der dritte Teil. Klicken Sie für den ersten Teil bitte auf „Schnell die Grundlagen von JavaScript-Interviews beherrschen“ (1))

Empfohlene verwandte Artikel:Die umfassendste Sammlung von js-Interviewfragen im Jahr 2020 (aktuell)

neue Schlüsselwörter

Wenn Sie das Schlüsselwort new verwenden, um eine Funktion auf ganz besondere Weise aufzurufen. Wir nennen die mit new aufgerufenen Funktionen Konstruktorfunktionen.

Was genau macht die Funktion mit new?

  • Erstellen Sie ein neues Objekt

  • Setzen Sie den Prototyp des Objekts auf den Prototyp des Konstruktors

  • Führen Sie das aus Konstruktor, thisdas neu erstellte Objekt ausführen

  • das Objekt zurückgeben. Wenn der Konstruktor ein Objekt zurückgibt, wird das konstruierte Objekt zurückgegeben.

// 为了更好地理解底层,我们来定义new关键字
function myNew(constructor, ...arguments) {
  var obj = {}
  Object.setPrototypeOf(obj, constructor.prototype);
  return constructor.apply(obj, arguments) || obj
}

Was ist der Unterschied zwischen der Verwendung von new und der Nichtverwendung?

function Bird() {
  this.wings = 2;
}
/* 普通的函数调用 */
let fakeBird = Bird();
console.log(fakeBird);    // undefined
/* 使用new调用 */
let realBird= new Bird();
console.log(realBird)     // { wings: 2 }

Um den Vergleich und das Verständnis zu erleichtern, hat der Übersetzer eine zusätzliche Testsituation hinzugefügt:

function MBird(){
  this.wings =2; 
  return "hello";
}

let realMBrid = new MBird();
console.log(realMBird) // { wings: 2 }

Sie werden feststellen, dass dieser Satz return "hello" keine Wirkung hat!

Prototyp und Vererbung

Prototyp ist das verwirrendste Konzept in JavaScript. Einer der Gründe dafür ist, dass prototype in zwei verschiedenen Situationen verwendet werden kann.

  • Prototyp-Beziehung
    Jedes Objekt hat ein prototype-Objekt, das alle Eigenschaften seines Prototyps enthält.
    .__proto__ ist ein informeller Mechanismus (bereitgestellt in ES6), der verwendet wird, um den Prototyp eines Objekts zu erhalten. Sie können es verstehen, da es auf das parent des Objekts verweist.
    Alle gewöhnlichen Objekte erben das Attribut .constructor, das auf den Konstruktor des Objekts verweist. Wenn ein Objekt über einen Konstruktor implementiert wird, zeigt das __proto__-Attribut auf das .prototype des Konstruktors des Konstruktors. Object.getPrototypeOf() ist eine Standardfunktion von ES5, die verwendet wird, um den Prototyp eines Objekts zu erhalten.

  • Prototyp-Eigenschaften
    Jede Funktion verfügt über eine .prototype-Eigenschaft, die alle Eigenschaften enthält, die vererbt werden können. Standardmäßig enthält dieses Objekt ein .constructor-Attribut, das auf den ursprünglichen Konstruktor verweist. Jedes mit einem Konstruktor erstellte Objekt verfügt über eine Konstruktoreigenschaft.

Das Folgende ist ein Beispiel zum besseren Verständnis:

function Dog(breed, name){
  this.breed = breed,
  this.name = name
}
Dog.prototype.describe = function() {
  console.log(`${this.name} is a ${this.breed}`)
}
const rusty = new Dog('Beagle', 'Rusty');

/* .prototype 属性包含了构造函数以及构造函数中在prototype上定义的属性。*/
console.log(Dog.prototype)  // { describe: ƒ , constructor: ƒ }

/* 使用Dog构造函数构造的对象 */
console.log(rusty)   //  { breed: "Beagle", name: "Rusty" }
/* 从构造函数的原型中继承下来的属性或函数 */
console.log(rusty.describe())   // "Rusty is a Beagle"
/* .__proto__ 属性指向构造函数的.prototype属性 */
console.log(rusty.__proto__)    // { describe: ƒ , constructor: ƒ }
/* .constructor 属性指向构造函数 */
console.log(rusty.constructor)  // ƒ Dog(breed, name) { ... }

Der Einsatz von JavaScript kann als recht flexibel bezeichnet werden, um Fehler zu vermeiden , können Sie auch Enter Fundebug für die Online-Echtzeitüberwachung akzeptieren.

Prototypenkette

Prototypenkette bezieht sich auf Objekte, die durch Prototypen zu einer gerichteten Kette verbunden sind. Beim Zugriff auf eine Eigenschaft eines Objekts prüft die JavaScript-Engine zunächst, ob das Objekt die Eigenschaft enthält. Wenn nicht, prüfen Sie, ob es im Prototyp des Objekts enthalten ist. Und so weiter, bis die Immobilie gefunden ist oder das letzte Objekt gefunden ist. Der Prototyp des letzten Objekts ist standardmäßig null.

Besitzen vs. Vererben

Ein Objekt verfügt über zwei Arten von Eigenschaften, nämlich seine eigenen definierten und geerbten Eigenschaften.

function Car() { }
Car.prototype.wheels = 4;
Car.prototype.airbags = 1;

var myCar = new Car();
myCar.color = 'black';

/*  原型链中的属性也可以通过in来查看:  */
console.log('airbags' in myCar)  // true
console.log(myCar.wheels)        // 4
console.log(myCar.year)          // undefined

/*  通过hasOwnProperty来查看是否拥有该属性:  */
console.log(myCar.hasOwnProperty('airbags'))  // false — Inherited
console.log(myCar.hasOwnProperty('color'))    // true

Object.create(obj) erstellt ein neues Objekt, dessen Prototyp auf obj zeigt.

var dog = { legs: 4 };
var myDog = Object.create(dog);

console.log(myDog.hasOwnProperty('legs'))  // false
console.log(myDog.legs)                    // 4
console.log(myDog.__proto__ === dog)       // true

Vererbung wird per Referenz übergeben

Geerbte Eigenschaften werden alle per Referenz übergeben. Lassen Sie es uns anhand von Beispielen anschaulich verstehen:

var objProt = { text: 'original' };
var objAttachedToProt = Object.create(objProt);
console.log(objAttachedToProt.text)   // original

// 我们更改objProt的text属性,objAttachedToProt的text属性同样更改了
objProt.text = 'prototype property changed';
console.log(objAttachedToProt.text)   // prototype property changed

// 但是如果我们讲一个新的对象赋值给objProt,那么objAttachedToProt的text属性不受影响
objProt = { text: 'replacing property' };
console.log(objAttachedToProt.text)   // prototype property changed

Klassische Vererbung vs. prototypische Vererbung

Eric Elliotts Artikel enthält eine sehr detaillierte Einführung: Master the JavaScript Interview: Was ist der Unterschied zwischen Klassen- und prototypischer Vererbung? ?
Der Autor glaubt, dass die prototypische Vererbung der klassischen Vererbung überlegen ist, und bietet eine Videoeinführung: https://www.youtube.com/watch...

Asynchrones JavaScript

JavaScript ist eine Single-Threaded-Programmiersprache, was bedeutet, dass die JavaScript-Engine jeweils nur einen bestimmten Codeabschnitt ausführen kann. Das dadurch verursachte Problem ist: Wenn die Ausführung eines Codeabschnitts lange dauert, bleiben andere Vorgänge hängen. JavaScript verwendet Call Stack, um Funktionsaufrufe aufzuzeichnen. Ein Call Stack kann als Stapel Bücher betrachtet werden. Das letzte Buch wird oben aufgelegt und zuerst entnommen. Die zuerst abgelegten Bücher liegen unten und werden zuletzt entnommen.

Um zu verhindern, dass komplexer Code die CPU zu lange belegt, besteht eine Lösung darin, eine asynchrone Callback-Funktion zu definieren. Definieren wir selbst eine asynchrone Funktion:

function greetingAsync(name, callback){
  let greeting = "hello, " + name ;
  setTimeout(_ => callback(greeting),0);
}

greetingAsync("fundebug", console.log);
console.log("start greeting");

我们在greetingAsync中构造了greeting语句,然后通过setTimeout定义了异步,callback函数,是为了让用户自己去定义greeting的具体方式。为方便起见,我们时候直接使用console.log
上面代码执行首先会打印start greeting,然后才是hello, fundebug。也就是说,greetingAsync的回调函数后执行。在网站开发中,和服务器交互的时候需要不断地发送各种请求,而一个页面可能有几十个请求。如果我们一个一个按照顺序来请求并等待结果,串行的执行会使得网页加载很慢。通过异步的方式,我们可以先发请求,然后在回调中处理请求结果,高效低并发处理。

下面通过一个例子来描述整个执行过程:

const first = function () {
  console.log('First message')
}
const second = function () {
  console.log('Second message')
}
const third = function() {
  console.log('Third message')
}

first();
setTimeout(second, 0);
third();

// 输出:
  // First message
  // Third message
  // Second message
  1. 初始状态下,浏览器控制台没有输出,并且事件管理器(Event Manager)是空的;

  2. first()被添加到调用栈

  3. console.log("First message")加到调用栈

  4. console.log("First message")执行并输出“First message”到控制台

  5. console.log("First message")从调用栈中移除

  6. first()从调用栈中移除

  7. setTimeout(second, 0)加到调用栈

  8. setTimeout(second, 0)执行,0ms之后,second()被加到回调队列

  9. setTimeout(second, 0)从调用栈中移除

  10. third()加到调用栈

  11. console.log("Third message")加到调用栈

  12. console.log("Third message")执行并输出“Third message”到控制台

  13. console.log("Third message")从调用栈中移除

  14. third()从调用栈中移除

  15. Event Loop 将second()从回调队列移到调用栈

  16. console.log("Second message")加到调用栈

  17. console.log("Second message")Second message”到控制台

  18. console.log("Second message")从调用栈中移除

  19. Second()从调用栈中移除

特别注意的是:second()函数在0ms之后并没有立即执行,你传入到setTimeout()函数的时间和second()延迟执行的时间并不一定直接相关。事件管理器等到setTimeout()设置的时间到期才会将其加入回调队列,而回调队列中它执行的时间和它在队列中的位置已经它前面的函数的执行时间有关。

相关学习推荐:javascript视频教程

Das obige ist der detaillierte Inhalt vonTeilen von Fragen zum Grundwissen von JavaScript-Interviews. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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