私たちはあなたにとって面白くて珍しいことをしようとしました。 私たちが成功することを本当に願っています。 なぜそうなのか、答えも説明もなしにあなたを去りたくありませんでした。 正しくしましょう。
そもそも、コンテストの様子を思い出していただきたいと思います。JSに関する15の質問の4ラウンド、Reactに関する15の質問のラウンドのうちの1つ、10の質問の決勝がありました。
カットの下-最初の4ラウンドのタスクの分析。
どうやってこれをやったの? 選択できるストックがあるように、約80〜90の質問を生成する必要があると判断しました。 その後、すべてをトピックに分割しました。
- ブラウザイベント
- さまざまなAPI(Array、Set、definePropertyなど)、
- 気配り
- 分数を扱う
- 巻き上げ
- イベントループ
- 型変換
- タイプ
- 論理(論理ANDおよびOR)
その後、質問は4ラウンドに渡って配布されました。 すべてのツアーの複雑さを同じにするために、これらのテストに合格し、質問が簡単な場所、困難な場所を特定し、未解決の質問をより適切な質問に置き換えて何度か訪問しました。 そして、各ラウンドの特定のトピックについて、ほぼ同数の質問を作成しました。 その結果、異なるツアーで似たような質問がありましたが、同じ質問ではなかったことが判明しました。
このため、多くの重複した説明が存在するため、ツアーを整理するのはあまり便利ではないようです。トピックごとにそれらを確認することをお勧めします。 最も単純なものから始めましょう。
注目すべき質問:
コンソールには何が表示されますか?
console.log(0,1 + 0,2); a) 0.30000000000000004 b) 0.3 c) 2 d) 0 1 2
d)0 1 2
ここは数字の間にあり、ではありません.
質問を次のようにフォーマットすると:
console.log(0, 1 + 0, 2);
すべてが明らかになります
コンソールには何が表示されますか?
(() => { 'use strict'; a = null + undefined; console.log(a); })(); a) 0 b) NaN c) null d)
d)エラー
a
は変数として(変数宣言ではなく)作成されないため、代入式が暗黙的にthis.a
割り当てられます。 グローバル変数window.a
はストリクトモードで作成されますが、これは禁止されています。
コンソールには何が表示されますか?
let foo = function bar() { return 123; }; console.log( typeof bar() ); a) 'function' b) 'number' c) 'undefined' d)
d)エラー
これは関数式(式)です。この場合、関数の名前は関数に対してローカルです。 関数を呼び出すには、 bar
ではなくfoo
を呼び出す必要がありbar
。 宣言の場合、答えはnumber
ます。
分数の取り扱いに関する質問:
コンソールには何が表示されますか?
console.log(0.1 ** 2); a) 0.2 b) 0.01 c) 0.010000000000000002 d) NaN
c)0.010000000000000002
コンソールには何が表示されますか?
console.log(0.1 + 0.2); a) 0.30000000000000004 b) 0.3 c) 2 d) NaN
質問にもう少し複雑になります。
ブラウザーのイベント:
要素にはイベントハンドラーがありますが、このハンドラー内の値は常に同じですか?
elem.onclick = function(event) { } a) event.target event.currentTarget b) event.target this c) event.currentTarget this d)
c)event.currentTargetおよびこれ
this-常に要素を指します
currentTarget
イベントがハングする要素
target
イベントが発生した要素
divをクリックすると、このコードは何を出力しますか?
div.onclick = function() { console.log(1) }; div.onclick = function() { console.log(2) }; div.addEventListener('click', function() { console.log(3) }); a) 1 b) 1 3 c) 2 3 d) 3
c)2 3
onclickはconsole.log(1)
ハンドラーを追加しconsole.log(1)
が、次の行では新しい関数でそれをグラインドし、 console.log(2)
のみが残ります。 onclick
はDOMプロパティであり、常に1です
イベントは、ハングした順序で機能し、最初の2、次に3が表示されます。
addEventListener
数回実行すると、それぞれが機能します。 ハンドラーはイベントをキューに追加します。
さまざまなAPIに関する質問セクション
defineProperty:
このコードは何を出力しますか?
(() => { const obj = { key: 1 }; Object.defineProperty(obj, 'key', { enumerable: false, configurable: false, writable: false, value: 2 }); console.log(obj.key); obj.key = 3; console.log(obj.key); })(); a) 1, 2 b) 2, 2 c) 2, 3 d)
b)2、2
このコードは何を出力しますか?
(() => { 'use strict'; const obj = { key: 1 }; Object.defineProperty(obj, 'key', { enumerable: false, configurable: false, writable: false, value: 2 }); console.log(obj.key); obj.key = 3; console.log(obj.key); })(); a) 1, 2 b) 2, 2 c) 2, 3 d) 2,
d)2、エラー
このコードは何を出力しますか?
(() => { const obj = { key: 1 }; Object.defineProperty(obj, 'key', { enumerable: false, configurable: false, writable: true, value: 2 }); console.log(obj.key); obj.key = 3; console.log(obj.key); })(); a) 1, 2 b) 2, 2 c) 2, 3 d)
c)2、3
上記のすべての質問では、 defineProperty
メソッドの知識、より具体的にはwritable
設定がdefineProperty
ます。 false
設定されている場合、 defineProperty
2番目のパラメーターによって渡されるキーの値を変更することは禁止されています。 唯一の違いは、ストリクトモードがない場合、ストリクトモードをuse strict
すると、すべてが正常であるように見せかけますが、値は変更されず、ストリクトモードではエラーが発生します。
増分:
このコードは何を出力しますか?
let x = 5; console.log(x++); a) 5 b) 6 c) '5++' d)
a)5
このコードは何を出力しますか?
const a = 5; console.log(a++); a) 5 b) 6 c) '5++' d)
d)エラー
接尾辞形式の犯罪を使用する場合、値は増加する前に返されます。
そしてプレフィックスの後に、すなわち console.log(++5)
は6
const
は上書きできません。 数値はプリミティブです。インクリメントすると、変数は新しい値で上書きされ、エラーが発生します。
セット:
このコードは何を出力しますか?
const a = [...new Set([1, 1, 2, , 3, , 4, 5, 5])]; console.log(a); a) [1, 1, 2, , 3, , 4, 5, 5] b) [1, 2, undefined, 3, 4, 5] c) [1, 1, 2, undefined, 3, undefined, 4, 5, 5] d)
b)[1、2、未定義、3、4、5]
このコードは何を出力しますか?
let set = new Set([10, '10', new Number(10), 1e1, 0xA]); console.log(set.size); a) 5 b) 3 c) 2 d) 1
b)3
このコードは何を出力しますか?
let obj = {}; let set = new Set([obj, obj, {}, {}, {...{}}, {...obj}]); console.log(set.size); a) 6 b) 5 c) 2 d) 1
b)5
Set
はセットであり、定義上、同じ値を設定することはできません。 問題は、これらの値をどのように比較するかです。 プリミティブは値によって比較され、オブジェクトは参照によって比較されます。
それ自体はデータ型を引用せず、任意の型1e1
および0xA
値を格納できます1e1
進法に変換され、10を取得します。
そして、新しいオブジェクトは常に等しくありません: console.log({} == {})
はfalse
を返しfalse
オブジェクトはメモリのさまざまな場所に新しい方法で作成され、それらのリンクは等しくありません。
このコードは何を出力しますか?
console.log(Infinity / Infinity); a) NaN b) 1 c) Error d) Infinity
a)NaN
無限大を無限大に分割し、無限大から無限大を減算することは不可能です。 数学的な観点からは、不確実性が得られますInfinity
と0
エラーを乗算しても数学的な操作が発生しない場合に同じことが起こりますNaN
スプレッドに関する質問:
このコードは何を出力しますか?
const a = { ...{ a: 1, b: 2, c: 3 }, ...{ a: 2, c: 4, d: 8 } }; console.log(a); a) { a: 2, b: 2, c: 4, d: 8 } c) { a: 1, b: 2, c: 3, d: 8 } c) { a: 1, b: 2, c: 3, a: 2, c: 4, d: 8 } d)
a){a:2、b:2、c:4、d:8}
このコードは何を出力しますか?
const a = [...[1, 2], ...[[3, 4]], ...[5, 6]]; console.log(a); a) [1, 2, 3, 4, 5, 6] b) [1, 2, [3, 4], 5, 6] c) [[1, 2], [[3, 4]], 5, 6] e)
b)[1、2、[3、4]、5、6]
Spread
演算子は、オブジェクトまたは配列を部分に解析するのに役立ちます。 ...
後のエンティティから値を取得し、作成された値にコピーします。 配列とオブジェクトの場合、1レベルまで開くことに注意してください。 ...[[1]]
は、要素自体ではなく、1つの要素を持つ配列を返します。 オブジェクトに重複した値を含めることはできません。したがって、後に公開された値は、以前に公開された値によって上書きされます。 これを使用して、デフォルト設定を指定できます。
const fn = (actualProps) => ({ ...defaultProps, ...actualProps })
すべてのデフォルト値は、渡された値があれば、それによってオーバーライドされます。
このコードは何を出力しますか?
console.log(parseInt(' -10,3 ')); a) -10,3 b) -10 c) TypeError d) NaN
b)-10
MDNを使用した包括的な説明:
parseInt関数は、指定された番号体系の数字ではない文字を検出すると、この文字と後続のすべての文字をスキップし(適切な場合でも)、この文字の前の文字列の部分から変換された整数を返します。 parseIntは、数値の小数部分を切り捨てます。 行の先頭と末尾にスペースを使用できます。
このコードは何を出力しますか?
const t = { a: 6, b: 7 }; const p = new Proxy(t, { get() { return 12; }, }); console.log(pa); pa = 18; console.log(pa); console.log(ta); a) b) 12 18 18 c) 12 18 6 d) 12 12 18 e) 6 18 6
d)12 12 18
Proxy
は、オブジェクトへのすべての呼び出しをインターセプトします。 この場合、 get
メソッドのみをプロキシし、アクセスしているオブジェクトのどのフィールドに関係なく、常に12
を返します。 この場合、setには触れず、プロキシにアクセスすると、オブジェクトの値が置き換えられます。
配列:
このコードは何を出力しますか?
let arr = []; arr[1] = 1; arr[5] = 10; console.log(arr.length); a) 1 b) 5 c) 6 d) 10
c)6
このコードは何を出力しますか?
let arr = new Array(3); console.log(arr[1]); a) undefined b) 1 c) 3 d)
a)未定義
1つの数値引数でArray
を作成するとき、それは配列の長さを意味します。 配列は空で作成され、すべての値はundefined
です。 存在しない配列フィールドへのアクセスを作成すると、同じことが起こります。 Array
に数値を渡すと、この要素を持つ配列が返されることに注意してください。 Array('a')
は['a']
を返し['a']
論理演算&&
、 ||
、 ==
など:
このコードは何を出力しますか?
console.log([] && 'foo' && undefined && true && false); a) [] b) 'foo' c) undefined d) true
c)未定義
このコードは何を出力しますか?
console.log(0 || 1 && 2 || 3); a) 0 b) 1 c) 2 d) 3
c)2
このコードは何を出力しますか?
console.log(0 || '' || 2 || undefined || true || false); a) 0 b) false c) 2 d) true
c)2
このコードは何を出力しますか?
console.log(2 && '1' && null && undefined && true && false); a) 2 b) false c) undefined d) null
d)null
このコードは何を出力しますか?
console.log([] && {} || null && 100 || ''); a) true b) 100 c) '' d) {}
d){}
空のオブジェクト{}
とtrue
空の配列[]
はtrue
です。
空の文字列''
、 null
およびundefined
はfalse
論理的または||
-trueの場合、左のオペランドを返します。それ以外の場合、右のオペランドを返します。
論理および&&
-左側のオペランドがfalseの場合、それ以外の場合は右側のオペランドを返します。
これは、デフォルトのパラメーターが現れる前にコード内で見つかることがあります。関数にパラメーターがない場合は、デフォルトのパラメーターを使用します。
function f(userParams) { var params = userParams || defaultParams; }
現在、Reactは条件が真であるかどうかを頻繁にチェックしてから、何かをレンダリングします。
{ isDivVisible && <div>bla-bla</div> }
配列比較:
このコードは何を出力しますか?
const arrayFoo = [1, 2, 3, 4]; const arrayBaz = [1, 2, 3, 4]; console.log(arrayFoo == arrayBaz && arrayFoo == arrayBaz); a) false b) true c) undefined d)
a)偽
このコードは何を出力しますか?
console.log([null, 0, -0].map(x => 0 <= x)); a) [false, true, false] b) [false, true, true] c) [false, false, false] d) [true, true, true]
d)[true、true、true]
このコードは何を出力しますか?
const arrayFoo = [1, 2, 3, 4]; const arrayBaz = [1, 2, 3, 4]; console.log(arrayFoo >= arrayBaz && arrayFoo <= arrayBaz); a) true b) false c) undefined d)
a)true
このコードは何を出力しますか?
const foo = [1, 2, 3, 4]; const baz = '1,2,3,4'; console.log(foo >= baz && foo <= baz); a) false b) true c) undefined d)
b)true
==
参照による比較。
操作中に、 >, >=, <, <=
オペランドがプリミティブに変換され、 arrayFoo
メソッドがarrayFoo
で呼び出され、プリミティブ値arrayFoo
が返されますが、同じ配列への参照が返されます。 次に、 toString
メソッドを呼び出すことによりプリミティブ値への変換が行われます。このメソッドは、配列の文字列表現を「1,2,3,4」の形式で返し、2つの配列を辞書的に比較してtrue
を返しtrue
このコードは何を出力しますか?
console.log(+0 == -0); console.log(+0 === -0); console.log(Object.is(+0, -0)); a) true, false, false b) true, true, false c) false, true, true d) false, false. false
b)true、true、false
MDNによる包括的な説明:
このメソッドの動作( Object.is
についてObject.is
)は、 ===
演算子と同じではありません。 ===
演算子(および==
演算子)は、数値-0
と+0
等しいとNumber.NaN
、 Number.NaN
の値はそれ自体Number.NaN
は等しくNumber.NaN
ません。
巻き上げに関する質問:
このコードは何を出力しますか?
console.log(str); const str = 'HeadHunter'; a) 'HeadHunter' b) undefined c)
c)エラー
このコードは何を出力しますか?
var arrayFunction = []; for (let i = 0; i <= 10; i++) { arrayFunction.push(() => i); } console.log(arrayFunction[3]()); a) 4 b) 0 c) 11 d) 3
d)3
このコードは何を出力しますか?
console.log(str); var str = 'HeadHunter'; a) 'HeadHunter' b) undefined c) null c)
b)未定義
このコードは何を出力しますか?
console.log(foo); var foo; foo = foo ? 1 : 0; console.log(foo); a) b) undefined 0 c) '' 1 d) 0 0
b)未定義の0
関数呼び出しは機能しますか?
getCompanyName(); function getCompanyName() { return 'HeadHunter'; } a) b) , . c)
a)はい
このコードは何を出力しますか?
var arrayFunction = []; for (var i = 0; i <= 10; i++) { arrayFunction.push(() => i); } console.log(arrayFunction[3]()); a) 4 b) 0 c) 11 d) 3
c)11
関数宣言はポップアップしますが、式はありません。
var
ポップアップしますが、初期化がundefined
まで。
let
とconst
はポップアップせず、ブロック内にスコープを持ちます。 {}
限定されます。
var
ループが正しく機能するためには、クロージャーを使用する必要があります。値はその中に保存されます。
(これは以前はインタビューの古典的なタスクでしたが、今ではそうしました)
var arrayFunction = []; for (var i = 0; i <= 10; i++) { (function(i) { arrayFunction.push(() => i); })(i); } console.log(arrayFunction[3]());
このコードは何を出力しますか?
console.log(true + false); a) true b) false c) 1 d) 0
c)1
演算子はどれも文字列ではなく、 +
は数字になります。 1 + 0
このコードは何を出力しますか?
console.log([] - 100 + ![]); a) false b) '-100' c) -100 d) NaN
c)-100
配列は文字列にキャストされます。その後、 -
数値にキャストすると、 -100
になり、配列をfalse
キャストしfalse
。これは0
このコードは何を出力しますか?
console.log([[], []] + 1); a) 1 b) '1' c) ',1' d) NaN
c) '、1'
オブジェクトに対してtoString
をtoString
ますが、 toString
は配列のすべての要素に対しても呼び出されます。 [].toString
は空の文字列''
を返します。 判明したのは, + 1
答え,1
です。
このコードは何を出力しますか?
console.log([] + 100 + 5); a) 105 b) '1005' c) 1005 d) NaN
b) '1005'
配列は文字列に還元可能であり、その後、連結が既に発生しています。
このコードは何を出力しますか?
console.log(1 + { a: 3 } + '2'); a) 6 b) '1[object Object]2' c) 3 d) NaN
b) '1 [オブジェクトオブジェクト] 2'
文字列に変換-それは単なる連結です。
このコードは何を出力しますか?
console.log(10.toString() + 10 + 0x1); a) '10101' b) 21 c) '10100x1' d)
d)エラー
数値の場合、ドット.
は小数部の始まりを意味し、そこに数字が必要です-エラーが発生します。
この例をうまく動作させるには、 10..toString()
を記述する必要があります
このコードは何を出力しますか?
console.log(5 + false - null + true); a) '0true' b) NaN c) 6 d)
c)6
ここではすべてが数値に縮小され、 5 + 0 - 0 + 1
このコードは何を出力しますか?
console.log(true + NaN + false); a) true b) NaN c) false d) 1
b)NaN
NaN
数字を追加するとき、すべてを数字にしますNaN
を取得します
このコードは何を出力しますか?
console.log('0x1' + '1' - '1e1'); a) 17 b) 7 c) '0x111e1' d) NaN
b)7
最初の連結の後にすでに行があります。 '0x11' - '1e1'
を取得します。 サインのおかげで、すべてを数字にします。
0x11
進数の16進表記は17
です。
1e1
指数形式は1 * 10 ** 1
つまり わずか10
。
typeof:
このコードは何を出力しますか?
let foo = () => { return null; }; console.log( typeof typeof foo ); a) 'function' b) 'string' c) 'null' d)
b)「文字列」
このコードは何を出力しますか?
typeof function() {}.prototype; a) 'function' b) 'object' c) 'undefined' d)
b)「オブジェクト」
typeof
常に文字列を返し、関数を呼び出すよりも優先度が低いため、関数が最初に実行され、返された結果にtypeof
が適用されます。 FunctionオブジェクトはFunction.prototypeを継承します。 Speckはこれがオブジェクトであることを明示的に決定します。
イベントループ:
約束に関する2つの質問から始めましょう。
このコードは何を出力しますか?
Promise.reject() .then(() => console.log(1), () => console.log(2)) .then(() => console.log(3), () => console.log(4)); a) 1 4 b) 1 3 c) 2 3 d) 2 4
c)2 3
このコードは何を出力しますか?
Promise.reject('foo') .then(() => Promise.resolve('bar'), () => {}) .then((a) => {console.log(a)}) a) foo b) bar c) undefined d)
c)未定義
Promise.reject
拒否された状態のプロミスを返します。
then
、 onFulfill
およびonReject
コールバックの2つのパラメーターをonFulfill
ことにonFulfill
してonReject
。 それ以前にエラーが発生した場合、 onReject
コールバックにonReject
ます。 エラーがない場合は、次にonFulfill
then
ます。 また、 () => {}
は空のオブジェクトではなくundefined
返すことを忘れないでください。空のオブジェクトを返すには、次のように記述する必要があります。 () => ({})
タスクの順序。
このコードは何を出力しますか?
async function get1() { return 1; } function get2() { return 2; } (async () => { console.log(await get1()); })(); console.log(get2()); a) 1,2 b) 2,1 c) 1 d) 2
b)2.1
このコードは何を出力しますか?
setTimeout(() => {console.log('in timeout')}); Promise.resolve() .then(() => {console.log('in promise')}); console.log('after'); a) in timeout, in promise, after b) after, in promise, in timeout c) after, in timeout, in promise d) in timeout, after, in promise
b)約束通り、タイムアウト後
このコードは何を出力しますか?
let __promise = new Promise((res, rej) => { setTimeout(res, 1000); }); async function test(i) { await __promise; console.log(i); } test(1); test(2); a) 1, 2 b) 2, 1 c) 1 d) 2
a)1、2
このコードは何を出力しますか?
console.log('FUS'); setTimeout(() => {console.log('RO')}) Promise.resolve('DAH!').then(x => console.log(x)); a FUS RO DAH! b) FUS DAH! RO c) RO FUS DAH! d) DAH! RO FUS
b)FUS DAH! RO
このコードは何を出力しますか?
console.log(1); setTimeout(() => console.log('setTimeout'), 0); console.log(2); Promise.resolve().then(() => console.log('promise1 resolved')); console.log(3); a) 1, 2, 3, 'setTimeout', 'promise1 resolved' b) 1, 'setTimeout', 2, 'promise1 resolved', 3 c) 1, 2, 3, 'promise1 resolved', 'setTimeout' d) 1, 2, 'promise1 resolved', 3, 'setTimeout'
c)1、2、3、「promise1が解決」、「setTimeout」
最初に、すべての同期呼び出しがトリガーされ、その後、呼び出しスタックが空になると、キューに入れられたもの(非同期タスク)が呼び出されます。 最初のマイクロタスク-約束とmutation observer
。 現在のタスクの最後に、すべてのマイクロタスクが実行されます。このマイクロタスクに関連して、イベントループをブロックできます。ブラウザでタスクが完了すると、レンダリングが行われます。 この後、マクロタスク-タイムアウトが実行されます。
これは非常に単純化された例です。詳細については、ミハイル・バシュロフのスピーチを見ることをお勧めします
そして最後の質問は約束と待つ
このコードは何を出力しますか?
const p = Promise.resolve(); (async () => { await p; console.log('1'); })(); p.then(() => console.log('2')) .then(() => console.log('3'));
a)1 2 3
b)2 1 3
c)2 3 1
d)3 2 1
c)2 3 1
仕様によると、 then
追加されたプロミスは最初に実行され、 then
のみ続行する必要があります
非同期関数の実行。 スペック 。 これがなぜそうなのかをさらに詳しく理解するには、 v8.devの優れた記事を読むことをお勧めします。