Heim >Web-Frontend >js-Tutorial >Sprechen Sie über den Void-Operator in Javascript
Da JS-Ausdrücke in der Regel umständlich sind, verwende ich seit kurzem Coffeescript, um den Aufwand zu verringern. Wenn ich beispielsweise den ersten Hund im Haus abrufen möchte, muss ich zunächst feststellen, ob das Hausobjekt vorhanden ist, dann feststellen, ob house.dogs vorhanden ist, und schließlich house.dogs[0] abrufen. In JS muss ich so schreiben
var dog = (typeof house !== 'undefined && house !== null) && house.dogs && house.dogs[0]
In Coffee muss ich nur so schreiben:
dog = house?.dogs?[0];
An diesem Punkt werden sich die Leser fragen, ob das etwas hat mit dem Titel „void in Javascript“ zu tun. Gibt es eine Dime-Beziehung? Die Essenz von Coffee ist JS. Der Grund, warum Coffee so gut funktioniert, liegt darin, dass es effizienten und robusten JS-Code generiert.
var dog, _ref; dog = typeof house !== "undefined" && house !== null ? (_ref = house.dogs) != null ? _ref[0] : void 0 : void 0;
Nur eine Zeile Coffee-Code hat einen so langen JS-Code generiert, der zuverlässiger und sicherer zu sein scheint als der, den ich zuvor in JS geschrieben habe. Am Ende stehen auch zwei leere Nullen ist das?
Strukturieren Sie das obige Beispiel:
dog = (typeof house !== "undefined" && house !== null) ? ((_ref = house.dogs) != null ? _ref[0] : void 0 ) : void 0;
Wenn Haus undefiniert oder Haus null ist, geben Sie void 0 zurück
Wenn house.dogs null ist, geben Sie void 0 zurück
Aber was ist der Wert von void 0? Das ist leicht zu testen:
typeof void 0 //得到"undefined"console.log(void 0) //输出undefined
Es scheint, dass void 0 undefiniert ist, aber diese Methode ist zu wild und nicht streng genug, das ist nicht möglich Um zu antworten: Was sind die Werte der unzähligen möglichen Kombinationen von void 100, void hello(), void i++?
Werfen wir einen Blick auf die Normen.
Die Spezifikation besagt Folgendes
In der ECMAScript 262-Spezifikation gibt es die folgende Beschreibung:
The void Operator The production UnaryExpression : void UnaryExpression is evaluated as follows: Let expr be the result of evaluating UnaryExpression. Call GetValue(expr). Return undefined. NOTE: GetValue must be called even though its value is not used because it may have observable side-effects.
Übersetzung:
void操作符 产生式 UnaryExpression : void UnaryExpression 按如下流程解释: 令 expr 为解释执行UnaryExpression的结果。 调用 GetValue(expr). 返回 undefined. 注意:GetValue一定要调用,即使它的值不会被用到,但是这个表达式可能会有副作用(side-effects)。
Der Schlüssel Der Punkt ist: Unabhängig vom Ausdruck nach void gibt der void-Operator undefiniert zurück. Daher können wir uns den von Coffee oben kompilierten Code wie folgt vorstellen:
dog = (typeof house !== "undefined" && house !== null) ? ((_ref = house.dogs) != null ? _ref[0] : undefined ) : undefined ;
Das Problem ist, da (void 0) === undefiniert, würde es nicht ausreichen, einfach undefiniert zu schreiben?
Warum void verwenden?
Weil undefiniert kein reserviertes Wort in Javascript ist. Mit anderen Worten, Sie können Folgendes schreiben:
function joke() { var undefined = "hello world"; console.log(undefined); //会输出"hello world" } console.log(undefined); //输出undefined
Ja, Sie können undefiniert als Variablennamen in einem Funktionskontext verwenden, sodass der in diesem Kontext geschriebene Code nur aus dem globalen Bereich in undefiniert abgerufen werden kann , wie zum Beispiel:
window.undefined //浏览器环境 GLOBAL.undefined //Node环境
Aber es sollte beachtet werden, dass selbst wenn window, GLOBAL immer noch im Funktionskontext definiert werden kann, sodass es nicht 100 % zuverlässig ist, von window/GLOBAL undefiniert zu werden. Zum Beispiel:
function x() { var undefined = 'hello world', f = {}, window = { 'undefined': 'joke' }; console.log(undefined);// hello world console.log(window.undefined); //joke console.log(f.a === undefined); //false console.log(f.a === void 0); //true }
Daher ist die Verwendung von void zum Erhalten von undefiniert zu einer allgemeinen Regel geworden. Beispielsweise wird isUndefiniert in underscore.js wie folgt geschrieben:
_.isUndefined = function(obj) { return obj === void 0; }
Gibt es neben der Verwendung von void, um sicherzustellen, dass der undefinierte Wert erhalten wird, noch andere Methoden? Ja, eine andere Möglichkeit ist der Funktionsaufruf. Beispielsweise verwendet der Quellcode von AngularJS diese Methode:
(function(window, document, undefined) { //..... })(window, document);
Durch die Nichtübergabe von Parametern wird sichergestellt, dass der Wert des undefinierten Parameters undefiniert ist.
Andere Funktionen
Gibt es außer der Verwendung von undefiniert noch andere Verwendungsmöglichkeiten für void?
Es gibt auch eine gemeinsame Funktion, das Ausfüllen von href. Unten sehen Sie einen Screenshot von Weibo. Seine Reposts, Sammlungen und Diskussionen sind alles Hyperlinks, aber Benutzer erwarten nicht, dass sie durch Klicken auf eine andere Seite springen, sondern einige interaktive Vorgänge auslösen.
Theoretisch haben diese drei Hyperlinks keine URL, aber wenn Sie sie nicht schreiben, hehe, wird durch Klicken darauf die gesamte Seite aktualisiert. Deshalb haben wir href="javascript:void(0) verwendet, um sicherzustellen, dass beim Klicken darauf ein rein langweiliges void(0) ausgeführt wird.
Eine andere Situation ist, wenn wir ein leeres src-Bild generieren möchten, der beste Weg scheint src='javascript:void(0)' zu sein
Am Ende geschrieben
Zurück zur Definition von void: Es gibt einen Satz, der besonders verwirrend ist:
Hinweis: GetValue muss aufgerufen werden, auch wenn sein Wert nicht verwendet wird, dieser Ausdruck kann jedoch Nebenwirkungen haben
.这是什么意思?这表示无论void右边的表达式是什么,都要对其求值。这么说可能不太明白,在知乎上winter大神有过阐述关于js中void,既然返回永远是undefined,那么GetValue有啥用?,我且拾人牙慧,代入一个场景,看代码:
var happiness = 10; var girl = { get whenMarry() { happiness--; return 1/0; //Infinity }, get happiness() { return happiness; } }; console.log(girl.whenMarry); //调用了whenMarry的get方法 console.log(girl.happiness); // 9 void girl.whenMarry; //调用了whenMarry的get方法 console.log(girl.happiness); // 8 delete girl.whenMarry; //没有调用whenMarry的get方法 console.log(girl.happiness); //还是8
上述代码定义了一个大龄文艺女青年,每被问到什么时候结婚呀(whenMarry),happiness都会减1。从执行情况可以看出,无论是普通访问girl.whenMarry,还是void girl.whenMarry都会使她的happiness--。而如果把void换成delete操作符写成delete girl.whenMarry,她的happiness就不会减了,因为delete操作符不会对girl.whenMarry求值。