JSの表現が冗長になりがちなので、負担を軽減するために最近Coffeescriptを使い始めました。たとえば、家の最初の犬を取得したい場合は、まず house オブジェクトが存在するかどうかを判断し、次に house.dogs が存在するかどうかを判断し、最後に house.dogs[0] を取得する必要があります。 JS では、次のように書く必要があります
var dog = (typeof house !== 'undefined && house !== null) && house.dogs && house.dogs[0]
Coffee では、次のように書くだけです:
dog = house?.dogs?[0];
これを書いた後、読者は、これはタイトルの "void in Javascript" と何か関係があるのかと尋ねるでしょう。 Coffee の本質は JS です。Coffee が非常にうまく機能する理由は、Coffee が効率的で堅牢な JS コードを生成するためです。生成された結果を見てみましょう。
var dog, _ref; dog = typeof house !== "undefined" && house !== null ? (_ref = house.dogs) != null ? _ref[0] : void 0 : void 0;
Coffee コードのたった 1 行で、これほど長い JS コードが生成されました。これは、以前に JS で書いたコードよりも信頼性が高く、安全であると思われます。最後には void が 2 つあります。これは誰ですか?
上記の例を構造化します:
dog = (typeof house !== "undefined" && house !== null) ? ((_ref = house.dogs) != null ? _ref[0] : void 0 ) : void 0;
houseが未定義またはhouseがnullの場合、void 0が返されます
house.dogsがnullの場合、void 0が返されます
しかし、void 0の値は何ですか?テストが簡単:
typeof void 0 //得到"undefined"console.log(void 0) //输出undefined
void 0 は未定義のようですが、この方法は乱暴すぎて厳密さが足りません。つまり、答えることは不可能です: void の無数の可能な組み合わせの値は何ですか100、void hello()、void i++?
規格の内容を見てみましょう。
仕様にはこう書いてあります
ECMAScript 262 仕様には次のような記述があります:
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.
翻訳:
void操作符 产生式 UnaryExpression : void UnaryExpression 按如下流程解释: 令 expr 为解释执行UnaryExpression的结果。 调用 GetValue(expr). 返回 undefined. 注意:GetValue一定要调用,即使它的值不会被用到,但是这个表达式可能会有副作用(side-effects)。
重要な点は、 void の後の式が何であっても、void 演算子は未定義を返すということです。 、上記は次のようになります。 Coffee によってコンパイルされたコードは次のように考えることができます:
dog = (typeof house !== "undefined" && house !== null) ? ((_ref = house.dogs) != null ? _ref[0] : undefined ) : undefined ;
質問は、 (void 0) === 未定義であるため、単に unknown と書くだけで十分ではないでしょうか?
なぜ void を使用するのですか?
未定義はJavaScriptの予約語ではないからです。つまり、次のように書くことができます:
function joke() { var undefined = "hello world"; console.log(undefined); //会输出"hello world" } console.log(undefined); //输出undefined
はい、関数コンテキストで変数名として unknown を使用できます。そのため、このコンテキストで記述されたコードは、次のようにグローバル スコープからのみ unknown を取得できます:
window.undefined //浏览器环境 GLOBAL.undefined //Node环境
しかし、それはwindow の場合でも、関数コンテキストで GLOBAL を定義できるため、window/GLOBAL から unknown を取得することは 100% 信頼できるわけではないことに注意してください。例:
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 }
そのため、void を使用して未定義を取得するのが一般的なルールになりました。たとえば、underscore.js の isUnknown は次のように記述されます:
_.isUndefined = function(obj) { return obj === void 0; }
未定義の値を確実に取得するために void を使用する以外に、他の方法はありますか?はい、もう 1 つの方法は関数呼び出しを使用することです。たとえば、AngularJS のソース コードでは次のメソッドが使用されています:
(function(window, document, undefined) { //..... })(window, document);
パラメーターを渡さないことで、未定義パラメーターの値が未定義であることが保証されます。
その他の関数
未定義を取得する以外に、void の用途はありますか?
hrefを埋めるという共通の関数もあります。以下は Weibo のスクリーンショットです。その転送、お気に入り、ディスカッションはすべてハイパーリンクですが、ユーザーはそれらをクリックして別のページにジャンプするのではなく、何らかのインタラクティブな操作をトリガーしたいと考えています。
理論的には、これら 3 つのハイパーリンクには URL がありませんが、書かないと、ふふふ、クリックするとページ全体が更新されます。そこで、クリックするとまったく退屈な void(0) が実行されるようにするために、 href="javascript:void(0) を使用しました。
別の状況では、空の src 画像を生成したい場合、最良の方法は src= のようです。 'javascript:void(0)'
最後に書いてあります
void の定義に戻ると、特に混乱を招く文があります:
注: 値が使用されない場合でも、GetValue を呼び出す必要があります。ただし、この式には副作用がある可能性があります
。这是什么意思?这表示无论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求值。