Javascript の奇妙な点をご存知ですか?

Javascript の奇妙な点をご存知ですか?

私たちのベテランの先人たちは、数え切れないほどのコードを書き、数え切れないほどの落とし穴に陥ってきました。しかし、ビジネスコードでは決して起こらない落とし穴がいくつかあるので、人生では決して踏み込んだり触れたりしないかもしれません~~

1

Function.prototype は実際には関数型です。カスタム関数のプロトタイプはオブジェクト型です。

typeof Function.prototype === 'function'; // true

関数 People() {}
typeof People.prototype === 'object'; // true

したがって、次のように空の関数を設定できます。

// わかりました 
const noop = Function.prototype;
// わかりました
定数 noop = () => {};

2

変数が本当にそれ自身と等しくないことはあり得るのでしょうか?

定数x = NaN;
x !== x // 真

これは、今のところ js 言語でそれ自身と等しくない唯一のデータです。なぜ? NaN は特定の値ではなく範囲を表すためです。
以前の isNaN() 関数では、文字列が渡されても true が返されていました。この問題は es6 で修正されました。

isNaN('abc'); // 真
Number.isNaN('abc') // false

したがって、古いブラウザとの互換性を維持したい場合は、 x !== x を使用して NaN かどうかを判断するのが適切な解決策です。

3

コンストラクタが新しいデータを返す場合

// 関数 People() を返さない {}
const people = new People(); // 人 {}

// 数値を返す function People() {
 1 を返します。
}
const people = new People(); // 人 {}

// 新しいオブジェクトを返す function Animal() {
 戻る {
  こんにちは世界'、
 };
}
const animal = new Animal(); // { hello: 'world' }

コンストラクタをインスタンス化するときに、非オブジェクト型を返すと動作しません。

4

.call.call 誰を応援してるの?

関数fn1() {
 コンソールログ(1);
}

関数fn2() {
 コンソールログ(2);
}

fn1.call.call(fn2); // 2

したがって、fn1.call.call(fn2) は fn2.call(undefined) と同等です。 .call をいくつ追加しても、効果は同じです。

5

インスタンス化されたオブジェクトを再度インスタンス化できますか?

関数 People() {}

const lili = new People(); // People {}
const lucy = new lili.constructor(); // 人 {}

lili のプロトタイプ チェーンは People プロトタイプを指しているため、プロパティを上方向に検索すると、最終的に Peopel.prototype 上のコンストラクターである People 自体が見つかります。

6

setTimeout をネストすると、どのような奇妙なことが起こりますか?

コンソールログ(0, Date.now());

タイムアウトを設定する(() => {
 コンソールログ(1, Date.now());
 タイムアウトを設定する(() => {
  コンソールログ(2, Date.now());
  タイムアウトを設定する(() => {
   コンソールログ(3, Date.now());
   タイムアウトを設定する(() => {
    コンソールログ(4, Date.now());
    タイムアウトを設定する(() => {
     コンソールログ(5, Date.now());
     タイムアウトを設定する(() => {
      コンソールログ(6, Date.now());
     });
    });
   });
  });
 });
});

レイヤー 0 ~ 4 では、setTimeout 間隔は 1 ミリ秒ですが、レイヤー 5 では間隔は少なくとも 4 ミリ秒です。

7

デフォルトパラメータを持つes6関数は宣言スコープを生成します

var x = 10;

関数 fn(x = 2, y = 関数 () { 戻り値 x + 1 }) {
 var x = 5;
 y() を返します。
}

fn(); // 3

8

関数式(非関数宣言)内の関数名は上書きできません

定数 c = 関数 CC() {
 CC = 123;
 CC を返します。
};

c(); // 関数

もちろん、var CC = 123 を設定した場合は、宣言キーワードを追加することで上書きできます。

9

厳密モードでは、関数のthisはWindowではなくundefinedになります。

// 非厳密関数 fn1() {
 これを返します。
}
fn1(); // ウィンドウ

// 厳密な関数 fn2() {
 '厳密な使用';
 これを返します。
}
fn2(); // 未定義

webpack によってパッケージ化されたモジュール化されたコードは、基本的に厳密モードのコードです。

10

丸め演算はビット演算を使用して行うこともできる。

var x = 1.23 | 0; // 1

ビット演算では 32 ビットの整数のみがサポートされるため、小数点はすべて破棄されます。

11

indexOf() は数値を比較する必要がなくなりました

定数arr = [1, 2, 3];

// 存在する、> -1 と同等
(〜arr.indexOf(1))の場合{

}

// 存在しない、=== -1 と同等
!~arr.indexOf(1);

ビット演算はより効率的になり、コードはより簡潔になります。 es6 の include() も使用できます。ただし、オープンソース ライブラリを作成するときに互換性を考慮する必要がある場合は、indexOf を使用することをお勧めします。

12

ゲッター/セッターも動的に設定できますか?

クラスHello {
 _name = 'ルーシー';
 
 取得名() {
  this._name を返します。
 }
 
 // 静的ゲッター
 IDを取得する() {
  1 を返します。
 }
}

定数 hel = 新しい Hello();

hel.name; // 未定義
hel.getName(); // ルーシー

// 動的ゲッター
Hello.prototype.__defineGetter__('name', function() {
 this._name を返します。
});

Hello.prototype.__defineSetter__('name', 関数(値) {
 this._name = 値;
});

hel.name; // ルーシー
hel.getName(); // ルーシー

hel.name = 'ジミ';
hel.name; // ジミ
hel.getName(); // ジミ

13

0.3 - 0.2 !== 0.1 // 真

浮動小数点演算は正確ではありませんが、これはよくあることですが、誤差は許容範囲内です。

0.3 - 0.2 - 0.1 <= Number.EPSILON // 真

14

クラス構文シュガーはどのように継承されますか?

関数Super() {
 1 を返します。
}

関数Child() {
 // プロパティ継承 Super.call(this);
 2 を 0 にします。
}
// プロトタイプ継承 Child.prototype = new Super();

定数child = 新しいChild();
子.a; // 1

正式なコードのプロトタイプ継承では、親クラスを直接インスタンス化するのではなく、動的プロパティの繰り返し宣言を避けるために空の関数をインスタンス化します。

const extends = (Child, Super) => {
 定数fn = 関数(){};
 
 fn.prototype = スーパープロトタイプ;
 Child.prototype = 新しい fn();
 Child.prototype.constructor = Child;
};

15

es6は実際にオブジェクトを繰り返し分解することができます

定数オブジェクト = {
 a: {
  1 です
 },
 2: 2 です
};

定数 a: { b }, a } = obj;

1 行のコードで a と ab の両方が取得されます。
a と b の両方が複数回使用される場合、一般的なロジックとしては、まず a を分解し、次の行で b を分解します。

16

コードが圧縮されているかどうかを判断するのはとてもクールです

関数 CustomFn() {}

const isCrashed = typeof CustomFn.name === 'string' && CustomFn.name === 'CustomFn';

17

オブジェクト === はメモリアドレスを比較し、 >= は変換された値を比較します。

{} === {} // 偽

// 暗黙的な変換 toString()
{} >= {} // 真

18

intanceofの判定方法は、プロトタイプが現在のオブジェクトのプロトタイプチェーン上にあるかどうかである。

関数 People() {}
関数 Man() {}
Man.prototype = 新しい People();
Man.prototype.constructor = Man;

man を新しい Man() に追加します。
man instanceof People; // true

//People のプロトタイプを置き換えます People.prototype = {};
man instanceof People; // false

es6クラスを使用する場合、プロトタイプprototypeは再定義できないため、上記のような状況は発生しません。

19

Object.prototype.__proto__ === null; // true

これはプロトタイプチェーンの最上位レベルであり、nullである。

20

数値が小さすぎるとparseIntはバグを引き起こします

parseInt(0.00000000454); // 4
parseInt(10.23); // 10

21

1 + ヌル // 1
1 + 未定義 // NaN

数値(null) // 0
数値(未定義) // NaN

22

実際のパラメータと形式パラメータは同期関係を維持する

関数テスト(a, b, c) {
 console.log(a, b, c); // 2, 3, 未定義
 
 引数[0] = 100;
 引数[1] = 200;
 引数[2] = 300;
 
 console.log(a, b, c); // 100、200、未定義
}
テスト(2, 3);

渡される実際のパラメータの数が不十分な場合、同期関係も失敗します。
この動作を回避するために、厳密モードを使用して、引数がコピーされるだけになるようにすることもできます。

23

ボイドは頑固な老人だ

void 0 === 未定義 // 真
void 1 === 未定義 // 真
void {} === 未定義 // true
void 'hello' === 未定義 // true
void void 0 === 未定義 // true

誰も誰とも関係ないよ〜〜

24

try/catch/finallyにも特定の実行順序がある

関数fn1() {
 コンソールログ('fn1');
 1 を返します。
}

関数fn2() {
 コンソールログ('fn2');
 2を返します。
}

関数 getData() {
 試す {
  新しいエラーをスローします('');
 } キャッチ (e) {
  fn1() を返します。
 ついに
  fn2() を返します。
 }
}

コンソールにログ出力します。

// 印刷順序: 'fn1'、'fn2'、2

try/catch コード ブロックで return xxyyzz; キーワードに遭遇すると、最初に xxyyzz が実行され、その値が一時変数に配置されます。次に、finally コード ブロックの内容が実行され、一時変数が返されます。
finally にも return aabbcc がある場合は、新しいデータ aabbcc がすぐに返されます。

25

複数の数値に等しい変数 x はありますか?

定数x = {
 値: 0,
 文字列を渡す
  ++this.value を返します。
 }
}

x == 1 && x == 2 && x == 3; // 真

暗黙的な変換を使用すると、これは難しいことではありません。

26

clearTimeout と clearInterval は互換的に使用できますか?

var タイムアウト = setTimeout(() => console.log(1), 1000);
var 間隔 = setInterval(() => console.log(2), 800);

クリアインターバル(タイムアウト);
clearTimeout(間隔);

答えは「はい」です。ほとんどのブラウザは相互クリーンアップ タイマーをサポートしていますが、対応するクリーンアップ機能を使用することをお勧めします。

27

以下の印刷順序は何ですか?

タイムアウトを設定する(() => {
 コンソールログ(1);
}, 0);

新しいPromise((resolve) => {
 コンソールログ(2);
 解決する();
}).then(() => console.log(3));

関数callMe() {
 コンソールログ(4);
}

(非同期() => {
 callMe() を待機します。
 コンソールログ(5);
})();

答えは、2、4、3、5、1です。

メインクエスト: 2、4
マイクロタスク: 3、5
マクロタスク: 1

28

null はオブジェクト型ですが、Object から継承されません。これは歴史的なバグのようなものです。非常に多くの人がこの機能を使用していたため、これを修正すると何千ものプログラムが壊れてしまいます。

typeof null === 'object'; // true
Object.prototype.toString.call(null); // [オブジェクト Null]
null インスタンスオブオブジェクト; // false

29

基本型 (null と undefined を除く) を操作する場合、エンジンは自動的にデータをオブジェクトにパッケージ化し、操作後にオブジェクトを破棄します。

'abc'.substr(1);
(123)固定(2)

したがって、プロトタイプチェーンが変更されない限り、追加されたデータは破棄されます。

定数データ = 'abc';
データ.x = 'y';
console.log(data.x); // 未定義

データ.__proto__.x = 'z';
console.log(data.x); // 'z'

30

安全値を超えるとデータは安全ではなくなる

Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2; // 真

// 2 ** 53 === 2 ** 53 + 1 と同等です。// true

31

関数パラメータにデフォルト値があると、認識が変わる

関数テスト(a, b = 1) {
 // エイリアス同期、非厳密モードでは同期されることが期待されます arguments[0] = 20;
 コンソールログ(a); // 2
}
// 関数パラメータの数を確認します。期待値は 2 です。
console.log(テストの長さ); // 1

テスト(123);

32

数値はすべて浮動小数点型です。ビット演算を実行する場合、js はまず数値を int 型に変換します。他の言語と比較すると、これは追加のパフォーマンスオーバーヘッドになります。

1 | 0 // 1
1.234 | 0 // 1
1.234 | 0.6 // 1

1 & 1 // 1
1.23 & 1.456 // 1

~1 // -2
~1.234 // -2

33

場所への割り当ては直接ジャンプできる

場所 = 'http://baidu.com';

34

「new」の別の使い方を知っていますか?

関数テスト() {
 console.log(new.target === Test); // true
}

新しいテスト();

サブクラスがインスタンス化されている場合、new.target は Test ではありません。このメソッドは抽象クラスの効果を実現できます。

35

+0と-0には違いがある

1/+0 === 無限大
1/-0 === -無限大

以上がJavascriptの変な知識の詳細ですが、ご存知ですか?JavaScriptの変な知識の詳細については、123WORDPRESS.COMの他の関連記事に注目してください!

以下もご興味があるかもしれません:
  • JavaScript の奇妙な日付変換方法のまとめ
  • コードを隠すための js の奇妙なスキル
  • JavaScript配列の奇妙な動作
  • 奇妙で最短のIEバージョン判定JSスクリプト
  • JavaScript での奇妙な IE ブラウザ判定方法
  • JavaScript における偽の値の奇妙な例

<<:  MySQLクエリプランでken_lenの値を計算する方法

>>:  Docker Toolboxを完全にアンインストールする方法

推薦する

Vue の新しいパートナー TypeScript クイックスタート実践記録

目次1. 公式の足場を使って構築する2. プロジェクトディレクトリ分析3. TypeScript の...

DockerはMariaDBのサブライブラリとサブテーブル、および読み書き分離機能を実装します

目次1. はじめに2. 環境整備1. 基本環境3.Mysqlマスタースレーブ構成をインストールする1...

Jsモジュールパッケージのエクスポートの使用法と違いにはインポートが必要

目次1. Commonjsのエクスポートとrequireの使用1.1 CommonJS エクスポート...

ウェブページからテキスト透かしを削除する2つの簡単な方法

<br /> 特定の Web サイトを閲覧して、優れた Web ページを見つけた場合、そ...

MySQL でのストアド プロシージャと関数の作成の詳細な説明

目次1. ストアドプロシージャ1.1. 基本構文1.2 実行権限を指定してストアドプロシージャを作成...

JavaScript の遅延読み込み属性パターンを理解する

従来、開発者はインスタンスで必要になる可能性のあるデータに対して JavaScript クラス内にプ...

Vue.js の watch メソッドと computed メソッドの違いの詳細な例

目次序文導入1. 作用機序2. 自然から3. 時計と計算の比較4. メソッドはデータロジックの関係を...

dockerにros2をインストールするための詳細な手順

目次メイントピック1. UbuntuにDockerをインストールする2. DockerにROS2-F...

Ubuntu 20.04 LTSの詳細なインストール履歴

この記事では、USB ブート ディスクの作成とシステムのインストールについて説明します。システム構成...

グリーンスタイルのウェブデザイン作品18点の最新コレクション

トイ・ストーリー3 オンラインマーケティングウェブサイトゼンモバイル鉄から鉄へスプラウトファンドバー...

Linux運用保守ツールSupervisor(プロセス管理ツール)のインストールと使用

1. はじめにSupervisor は Python で開発された汎用プロセス管理プログラムです。通...

Dockerコンテナでルート権限を取得する方法

まず、コンテナが稼働している必要がありますコンテナのCONTAINER IDは、sudo docke...

MySQL 8.0.19 のインストールと設定方法のグラフィックチュートリアル

この記事は、参考のためにMySQL 8.0.19のインストールと設定のグラフィックチュートリアルを記...

HTMLからReactを実装する方法を教えます

ReactとはReact は、効率的で高速なユーザー インターフェイスを構築するためのシンプルな J...

http:// の代わりに // を使用する利点は何ですか (アダプティブ https)

//デフォルトプロトコル/ デフォルト プロトコルの使用は、リソース アクセス プロトコルが現在の...