JavaScriptフロントエンド開発者へのインタビュー:最良の質問

私は最近、サンフランシスコのFreeCodeCampプロジェクトの参加者の会議に出席する機会がありました。 誰も知らない場合、Free Code CampはJavaScriptとWebプログラミングの学習専用のコミュニティです。 そこで、フロントエンドのデベロッパーポジションのインタビューの準備をしていた1人の人が、JavaScriptの質問をどのように解決すべきかを尋ねてきました。 私は少しグーグルで検索しましたが、リンクを張って「これらの質問とあなたの仕事をしてください」と言うことができる適切な質問のリストを見つけることができませんでした。 いくつかの リスト 私が見つけたいものに近くいくつか 非常にシンプル見えましたが、不完全であったか、実際のインタビューではほとんど誰も聞かない質問が含まれていました。



画像






最終的に、私は自分のリストを作成することにしました。 仕事を探しているときに私に尋ねた質問と、フロントエンド開発者の職に就く従業員を探しているときに尋ねた質問が含まれています。 一部の企業(Googleなど)は、効率的なアルゴリズムの設計などに特別な注意を払っています。 したがって、同様の会社で働きたい場合は、ここにリストされている質問に加えて、 CodeJamコンテストの問題を解決してください



ここでこれらの質問への回答を追加および編集します 。 何かを補完または改善したい場合は、プルリクエストに喜んでいます。



質問はいくつかのセクションに分かれています。





だからここに私の質問があります。



理論



インタビュー対象者は、このセクションの質問に触れる概念を明確に理解し、すべてを説明できる必要があります。 ここではプログラミングは不要です。



  1. O-Big表記とは何ですか?
  2. DOMとは何ですか?
  3. イベントループとは何ですか?
  4. 閉鎖とは何ですか?
  5. プロトタイプ継承はどのように機能し、従来の継承モデルとどのように違いますか? (私の意見では、これは特に有用な質問ではありませんが、多くの人が質問したいです。)
  6. thisキーワードはどのように機能しますか?
  7. イベントポップアップとは何ですか?このメカニズムはどのように機能しますか? (私もこの質問は好きではありませんが、インタビューでよく尋ねます。)
  8. クライアントとサーバー間でデータを交換するいくつかの方法を説明します。 いくつかのネットワークプロトコル(IP、TCP、HTTP / S / 2、UDP、RTC、DNSなど)がどのように機能するかについては詳しく説明しません。
  9. RESTとは何ですか?なぜこのテクノロジーが人気があるのですか?
  10. 私のサイトは遅いです。 診断と修正の手順について教えてください。 一般的な最適化アプローチを説明し、それらをいつ使用するかを教えてください。
  11. どのフレームワークを使用しましたか? 彼らの長所と短所は何ですか? なぜプログラマーはフレームワークを使用するのですか? フレームワークはどのような問題を解決しますか?


プログラミング



これらの質問に対する答えには、JavaScriptでの関数の実装が含まれます。 各質問の後に、ソリューションが正常に合格する必要があるテストが続きます。



▍簡単なタスク



  1. isPrime()



    関数を実装します。これは、渡された数値が素数であるかどうかを示すtrue



    またはfalse



    を返しtrue







     isPrime(0)                          // false isPrime(1)                          // false isPrime(17)                         // true isPrime(10000000000000)             // false
          
          





  2. 渡された数値の階乗を返すfactorial()



    関数を実装します。



     factorial(0)                        // 1 factorial(1)                        // 1 factorial(6)                        // 720
          
          





  3. n番目のフィボナッチ数を返すfib()



    関数を実装します。



     fib(0)                              // 0 fib(1)                              // 1 fib(10)                             // 55 fib(20)                             // 6765
          
          





  4. isSorted()



    関数を実装します。この関数は、渡された数値配列がソートされているかどうかに応じてtrue



    またはfalse



    を返しtrue







     isSorted([])                        // true isSorted([-Infinity, -5, 0, 3, 9])  // true isSorted([3, 9, -3, 10])            // false
          
          





  5. filter()



    関数の独自の実装を作成します。



     filter([1, 2, 3, 4], n => n < 3)    // [1, 2]
          
          





  6. reduce()



    独自の実装を作成します。



     reduce([1, 2, 3, 4], (a, b) => a + b, 0) // 10
          
          





  7. 渡された文字列の文字シーケンスを逆にする、 reverse()



    関数を実装します。 組み込みのreverse()



    関数を使用しないでください。



     reverse('')                         // '' reverse('abcdef')                   // 'fedcba'
          
          





  8. 配列のindexOf()



    関数の独自の実装を作成します。



     indexOf([1, 2, 3], 1)               // 0 indexOf([1, 2, 3], 4)               // -1
          
          





  9. isPalindrome()



    関数を実装します。この関数は、渡された文字列が回文であるかどうかに応じてtrue



    またはfalse



    を返しtrue



    (関数は大文字と小文字を区別せず、文字列にスペースが含まれます)。



     isPalindrome('')                                // true isPalindrome('abcdcba')                         // true isPalindrome('abcd')                            // false isPalindrome('A man a plan a canal Panama')     // true
          
          





  10. missing()



    関数を実装します。この関数は、1から特定の数nまでの一意の数字の並べ替えられていない配列(つまり、数字が繰り返されない)を受け取り、シーケンスにない数字を返します。 不足している番号が1つあるか、まったくない場合があります。



    関数がO(N)時間で問題を解決することを保証できますか? ヒント:使用できる優れた式が1つあります。



     missing([])                         // undefined missing([1, 4, 3])                  // 2 missing([2, 3, 4])                  // 1 missing([5, 1, 4, 2])               // 3 missing([1, 2, 3, 4])               // undefined
          
          





  11. i sBalanced()



    関数を実装します。この関数は、ストリングを受け取り、ストリング内の中括弧がバランスをとっているかどうかを示すtrue



    またはfalse



    を返しtrue







     isBalanced('}{')                      // false isBalanced('{{}')                     // false isBalanced('{}{}')                    // true isBalanced('foo { bar { baz } boo }') // true isBalanced('foo { bar { baz }')       // false isBalanced('foo { bar } }')           // false
          
          





dium中程度のクエスト



  1. fib2()



    関数を実装します。 これは、前のタスクグループのfib()



    関数に似ていますが、最大50までの数値をサポートしています。ヒント:メモ化を使用します。



     fib2(0)                               // 0 fib2(1)                               // 1 fib2(10)                              // 55 fib2(50)                              // 12586269025
          
          





  2. isBalanced2()



    関数を実装します。 これは、前のタスクグループのisBalanced()



    関数に似ていますが、3種類のブラケットをサポートしています:中括弧{}



    、正方形[]



    、および丸()



    。 不正なブラケットシーケンスを含む文字列を関数に渡す場合、関数はfalse



    返す必要がありfalse







     isBalanced2('(foo { bar (baz) [boo] })') // true isBalanced2('foo { bar { baz }')         // false isBalanced2('foo { (bar [baz] } )')      // false
          
          





  3. uniq()



    関数を実装します。これは、数値の配列を受け取り、その中に見つかった一意の数値を返します。 関数はO(N)時間でこの問題を解決できますか?



     uniq([])                              // [] uniq([1, 4, 2, 2, 3, 4, 8])           // [1, 4, 2, 3, 8]
          
          





  4. intersection()



    関数を実装します。この関数は2つの配列を取り、それらの交差を返します。 O(M + N)timeでこの問題を解決する関数を取得できますか? MNは配列の長さです?



     intersection([1, 5, 4, 2], [8, 91, 4, 1, 3])    // [4, 1] intersection([1, 5, 4, 2], [7, 12])             // []
          
          





  5. O(N×log(N))timeで数値配列をソートするsort()



    関数の実装を作成します。



     sort([])                              // [] sort([-4, 1, Infinity, 3, 3, 0])      // [-4, 0, 1, 3, 3, Infinity]
          
          





  6. include includes()



    関数を実装します。この関数は、渡された番号が、渡されたソート済み配列で発生するかどうかに応じてtrue



    またはfalse



    を返しtrue



    。 関数はO(log(N))時間でこの問題を解決できますか?



     includes([1, 3, 8, 10], 8)            // true includes([1, 3, 8, 8, 15], 15)        // true includes([1, 3, 8, 10, 15], 9)        // false
          
          





  7. assignDeep()



    関数を実装します。これはObject.assign()



    似ていますが、オブジェクトの深い結合を行います。 タスクを複雑にしないために、オブジェクトには数字と他のオブジェクトのみを含めることができるという仮定から進めることができます(配列や文字列などを含めることはできません)。



     assignDeep({ a: 1 }, {})              // { a: 1 } assignDeep({ a: 1 }, { a: 2 })        // { a: 2 } assignDeep({ a: 1 }, { a: { b: 2 } }) // { a: { b: 2 } } assignDeep({ a: { b: { c: 1 }}}, { a: { b: { d: 2 }}, e: 3 }) // { a: { b: { c: 1, d: 2 }}, e: 3 }
          
          





  8. reduceAsync()



    関数を実装します。これは、単純なタスクのグループのreduce()



    関数に似ていますが、promiseオブジェクトを返す関数と連携しますreduceAsync()



    オブジェクトは、それぞれ次のタスクに進む前に解決する必要があります。



     let a = () => Promise.resolve('a') let b = () => Promise.resolve('b') let c = () => new Promise(resolve => setTimeout(() => resolve('c'), 100)) await reduceAsync([a, b, c], (acc, value) => [...acc, value], []) // ['a', 'b', 'c'] await reduceAsync([a, c, b], (acc, value) => [...acc, value], ['d']) // ['d', 'a', 'c', 'b']
          
          





  9. reduceAsync()



    関数で作業するときと同じアプローチを使用して、 seq()



    関数を実装します。 この関数は、promiseオブジェクトを返し、それらを1つずつ解決する関数の配列を取る必要があります。



     let a = () => Promise.resolve('a') let b = () => Promise.resolve('b') let c = () => Promise.resolve('c') await seq([a, b, c])                  // ['a', 'b', 'c'] await seq([a, c, b])                  // ['a', 'c', 'b']
          
          





▍課題



このグループの一部のタスクは、データ構造の作成に関連しています。 機能のすべての微妙な点を覚えておく必要はありません。デバイスを理解するだけで十分ですが、提供するインターフェイスに関する情報はインターネットで見つけることができます。 次に、これらのデータ構造が使用される理由、他のデータ構造と比較した場合の制限事項を知る必要があります。



  1. 指定された文字列のすべての順列を含む文字列の配列を返すpermute()



    関数を実装します。



     permute('')             // [] permute('abc')          // ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
          
          





  2. debounce()



    関数の独自の実装を作成します。



     let a = () => console.log('foo') let b = debounce(a, 100) b() b() b() //      a()
          
          





  3. JavaScriptの組み込み配列( []



    )を使用せずにLinkedList



    クラスを実装します。 LinkedList



    は、 add()



    およびhas()



    2つのメソッドのみをサポートする必要がありhas()







     class LinkedList {...} let list = new LinkedList(1, 2, 3) list.add(4)                           // undefined list.add(5)                           // undefined list.has(1)                           // true list.has(4)                           // true list.has(6)                           // false
          
          





  4. 組み込みJavaScriptオブジェクト( {}



    )またはmap()



    関数を使用せずにHashMap



    クラスを実装します。 文字列を受け取って特定の数値を返すhash()



    関数が与えられました。 これらの番号はほとんど一意ですが、2つの番号が同じ番号に対応する可能性もあります。



     function hash (string) { return string   .split('')   .reduce((a, b) => ((a << 5) + a) + b.charCodeAt(0), 5381) }
          
          





    HashMap



    実装は、 get()



    およびset()



    2つのメソッドのみをサポートする必要があります。



     let map = new HashMap map.set('abc', 123)                   // undefined map.set('foo', 'bar')                 // undefined map.set('foo', 'baz')                 // undefined map.get('abc')                        // 123 map.get('foo')                        // 'baz' map.get('def')                        // undefined
          
          





  5. BinarySearchTree



    クラスを実装します。 add()



    has()



    remove()



    、およびsize()



    4つのメソッドをサポートする必要がありsize()







     let tree = new BinarySearchTree tree.add(1, 2, 3, 4) tree.add(5) tree.has(2)                           // true tree.has(5)                           // true tree.remove(3)                        // undefined tree.size()                           // 4
          
          





  6. BinaryTreeクラスを実装します。これは、幅優先検索、対称、順方向、逆方向の深さ検索機能をサポートします。



     let tree = new BinaryTree let fn = value => console.log(value) tree.add(1, 2, 3, 4) tree.bfs(fn)                          // undefined tree.inorder(fn)                      // undefined tree.preorder(fn)                     // undefined tree.postorder(fn)                    // undefined
          
          





デバッグ



次の質問に答えるときは、まず、表示されたコードが機能しない理由を理解してください。 エラーの原因を説明してください。 次に、問題を修正するためのいくつかのオプションを提案し、提案されたオプションの1つを実装してコードを書き直します。 その結果、プログラムは正しく動作するはずです。



  1. このコードはログにhey arnold



    hey amy



    を出力する必要がありますが、 hey arnold



    出力します。 なんで?



     function greet(person) { if (person == { name: 'amy' }) {   return 'hey amy' } else {   return 'hey arnold' } } greet({ name: 'amy' })
          
          





  2. このコードは、指定された順序で番号0, 1, 2, 3



    記録する必要がありますが、記録しません(ある日、このエラーが発生します。インタビューでこの質問をしたい人もいます)。



     for (var i = 0; i < 4; i++) { setTimeout(() => console.log(i), 0) }
          
          





  3. このコードはdoggo



    ログに出力する必要がありますが、 undefined



    のみを出力します。



     let dog = { name: 'doggo', sayName() {   console.log(this.name) } } let sayName = dog.sayName sayName()
          
          





  4. Dog



    オブジェクトのbark()



    メソッドを呼び出そうとすると、エラーがスローされます。 なんで?



     function Dog(name) { this.name = name } Dog.bark = function() { console.log(this.name + ' says woof') } let fido = new Dog('fido') fido.bark()
          
          





  5. isBig()



    関数が正確にこの結果を返すのはなぜですか?



     function isBig(thing) { if (thing == 0 || thing == 1 || thing == 2) {   return false } return true } isBig(1)    // false isBig([2])  // false isBig([3])  // true
          
          





システム設計



「システム設計」が何であるかわからない場合は、まずこれをお読みください。



1.ユーザーが入力したテキストの自動補完ウィジェットの実装について教えてください。 オートコンプリートデータがサーバーからダウンロードされます。 システムのクライアントとサーバーの部分を考慮してください。





2.クライアントパーツとサーバーパーツを説明するTwitterのようなサービスの実装について教えてください(この質問は友人のMichael Wuから盗まれました)。





まとめ



これらの質問が、面接に行く人とそれを行う人の両方に役立つことを願っています。 そして、あなたがどちらにも関係していない場合、質問はあなたが良いプログラミング形式で自分を維持するのに役立つと信じています。



ちなみに、練習したい場合はさらにいくつかの場所を見てみましょう: アルゴリズム設計マニュアルCodeJamコンペティションのタスク、 keon /アルゴリズムリポジトリ。 また、JS開発者に役立つリソースをいくつか紹介します。JavaScriptAllongeJSを知らない効果的なJavaScriptです。



親愛なる読者! このリストに追加する必要があると思われる質問がある場合(またはエラーを見つけた場合)、この資料の著者に連絡してください。



All Articles