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

推薦する

CSS3 で transform を使用した場合のフォントぼかしの解決方法の詳細な説明

この質問は非常に奇妙なので、あまり多くを語らずにコードに直接進みます。 .g-ダイアログラッパー{ ...

vue-router 4 の使用例の詳しい説明

目次1. インスタンスをインストールして作成する2. vue-router4の新機能2.1 動的ルー...

Reactフックの仕組み

目次1. React フックと純粋関数2. シンプルなmyUseState 3. myUseStat...

VMware仮想マシンブリッジによるインターネット相互接続を実現する方法

VMware をインストールして新しい仮想マシンを作成したら、オプション バーの [編集] - [仮...

MySQL データベースの詳細な説明 - 複数テーブル クエリ - 内部結合、外部結合、サブクエリ、相関サブクエリ

複数テーブルクエリ複数のテーブルから関連するクエリ結果を取得するには、単一の SELECT ステート...

Linux で SSH 経由でリモート ファイルシステムをマウントする方法の詳細な説明

SSHFS の機能: FUSE(Linux向けの最高のユーザー空間ファイルシステムフレームワーク)を...

Linux\Nginx 環境での仮想ドメイン名の設定とテスト検証

Nginx 仮想ドメイン名設定を使用すると、ドメイン名を購入せずに特定のドメイン名を介してローカル ...

XHTML CSSを使用して正式なブログを書く

ブログの正式名称は「Web log」で、中国語で「ネットワークログ」を意味します。後にブログに短縮さ...

ハッシュテーブルのJavaScript実装の詳細な説明

目次1. ハッシュテーブルの原理2. ハッシュテーブルの概念3. ハッシュ競合問題1. チェーンアド...

Nginx を使用して https ルートドメイン名への 301 リダイレクトを実装するためのサンプル コード

SEO とセキュリティを考慮して、301 リダイレクトが必要です。以下の一般的な処理には Nginx...

TypeScriptジェネリックの使用

目次1. 使いやすい2. 関数内でジェネリックを使用する3. クラス内でジェネリックを使用する4. ...

Vue でのキープアライブコンポーネントの使用例

問題の説明(キープアライブとは何か)キープアライブ 名前の通り、アクティブな状態を維持します。誰が活...

Docker を使用して静的 Web サイト アプリケーションを作成する (複数の方法)

静的ウェブサイトをホストできるサーバーは数多くあります。この記事では、nginx、apache、to...

Nginx Rewrite の使用シナリオと設定方法の分析

Nginx Rewriteの使用シナリオ1. URL アドレスジャンプ。たとえば、ユーザーが pm....

Centos7.5 構成 Java 環境のインストール Tomcat の説明

Tomcat は Java 言語をベースにした Web サーバー ソフトウェアです。この記事では主に...