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を完全にアンインストールする方法

推薦する

DockerコンテナがJupyterにアクセスできない問題の解決策

このプロジェクトでは、環境を構築するために Docker コンテナを使用します。Dockerfile...

Windows Server 2016 に Docker をインストールするプロセスと発生した問題

前提条件Windows Server でコンテナーを実行するには、Windows Server (半...

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

mysql 8.0.22 winx64のインストールと設定のグラフィックチュートリアルは参考までに、...

Web デザインのヒント: ページ レイアウトの簡単なルール

繰り返し: サイト全体で特定のページ デザイン スタイルを繰り返します。繰り返し要素としては、特定の...

JSタイマーを使用して要素を移動する

JS タイマーを使用して、要素に移動する効果のあるメソッドを作成します。実装のアイデアは、まず要素の...

MySQL v5.7.18 解凍バージョンのインストール詳細チュートリアル

MySQLをダウンロード5.1.1.1 より前のバージョン私のコンピュータは64ビットなので、Win...

Linuxで新しいユーザーを作成し、指定されたディレクトリへの権限を付与する

1 ユーザーを作成し、ユーザーのルートパスとパスワードを指定します useradd -d /home...

LinuxにMySQLをインストールし、外部ネットワークアクセスを構成する例

設定手順1. DNSが設定されているかどうかを確認するDNSが設定されていない場合は、前の記事を参照...

Linux centos7 環境での MySQL インストール チュートリアル

Linux centos7 環境に MySQL をインストールする手順の詳細な紹介MySQLをインス...

CentOS7仮想マシンで固定IPアドレスを設定する方法

私の開発環境は、VMWare 仮想マシンに CentOS をインストールし、ホスト ファイルにインタ...

MySQL 接続クエリを本当に学びましたか?

1. 内部結合クエリの概要内部結合は、アプリケーションで非常に一般的な結合操作であり、通常はデフォ...

CSSで制御可能な点線を実装する方法

序文CSS を使用して点線を生成するのは、フロントエンド開発者にとっては簡単です。一般的に、これを実...

MySQL 5.7 の /etc/my.cnf パラメータの紹介

以下は、mysql 5.7 の /etc/my.cnf の一般的なパラメータの一部です。これらを自分...

JS がビデオ弾幕効果を実現

これを実現するには、ES6 モジュール開発とオブザーバー モードを使用します。オブザーバー パターン...

React Hooksコンポーネント間で値を渡す方法の詳細な説明(tsを使用)

目次父から息子へ息子から父へクロスレベルコンポーネント(親から子孫)父から息子へpropsを通じて値...