JS面接問題まとめ(二)


1.変数の昇格
JSコードを実行すると、コードが関数に書かれていない限り、関数のコードは生産関数のコントロール環境になります.
b() // call b
console.log(a) // undefined

var a = 'Hello world'

function b() {
     
 console.log('call b') }
以上のアウトプットは明らかになったと思いますが、これは関数と変数のアップグレードのためです.通常のアップグレードの解釈は声明のコードを上に移動させるということです.これは誤りがなく、大幅に理解しやすいです.しかし、より正確な説明は、生産環境においては、二つの段階があります.一つ目の段階は作成の段階で、JS解凍器は昇格させる変数と関数を探し出し、メモリの中に空間を作っておきます.関数は関数全体をメモリに貯めます.変数は声明のみでundefinedとして与えられますので、第二段階、つまりコードの保存段階で、直接に使用できます.
  • は、リフティング中に同じ関数が一つの関数を覆い、関数が変数リフティング
  • より優先される.
    b() // call b second
    function b() {
         
    	console.log('call b first')
    }
    function b() {
         
    	console.log('call b second')
    }
    
    var b = 'Hello CSDN'
    
    varは生産の多くのエラーが発生しますので、ES 6にletを導入しました.letは声明の前で使用することはできませんが、これはよく言われるletが向上しないわけではありません.letが向上し、第一段階でメモリも彼のために空間を開発しました.しかし、この声明の特性により、声明の前で使用することはできません.
    2.bind、call、appyの違い
  • callおよびapplyは、いずれも変更された指向を解決するためである.使うのは同じです.ただ、伝え方が違うだけです.
  • は、一つ目のパラメータに加えて、callは一つのパラメータリストを受信することができ、appyは一つのパラメータ配列
  • だけを受け入れることができる.
    let a = {
         
    	 value: 1 
     }
    function getValue(name, age) {
         
    	 console.log(name)
    	 console.log(age)
    	 console.log(this.value) 
     }
    getValue.call(a, 'yck', '24')
    getValue.apply(a, ['yck', '24'])
    
    bindと他の2つの構法を採用するのも同じです.ただし、この構法は一つの関数を返します.そして、私たちはビッドによって柯⽙化を実現することができます.
    3.どのように一つのbind関数を実現しますか?
    下記の関数を実現するには、⼏個端的に考えることができます.
  • は第一のパラメータを渡さないので、デフォルトはwindow
  • です.
  • は、新しいオブジェクトがこの関数を実行することができるように、this指向を変更しました.考え方は新しいオブジェクトに一つの関数を追加して実行後に削除することができますか?
  • Function.prototype.myBind = function (context) {
         
     if (typeof this !== 'function') {
         
    	 throw new TypeError('Error')
     }
     var _this = this
     var args = [...arguments].slice(1)
     //       
     return function F() {
         
     //          ,     new F(),      
     if (this instanceof F) {
         
     	return new _this(...args, ...arguments)
     }
    	return _this.apply(context, args.concat(...arguments))
     } }
    
    4.どのように一つのカルル関数を実現しますか?
    Function.prototype.myCall = function (context) {
         
     var context = context || window
     //   context       
     // getValue.call(a, 'yck', '24') => a.fn = getValue
     context.fn = this
     //   context         
     var args = [...arguments].slice(1)
     // getValue.call(a, 'yck', '24') => a.fn('yck', '24')
     var result = context.fn(...args)
     //    fn
     delete context.fn
     return result
    }
    
    5.どのように一つのアプリ関数を実現しますか?
    Function.prototype.myApply = function (context) {
         
     var context = context || window
     context.fn = this
     var result
     //              
     //     ,         
     if (arguments[1]) {
         
      result = context.fn(...arguments[1])
     } else {
         
     result = context.fn()
     }
     delete context.fn
     return result
    }
    
    6.プロトタイプチェーン
  • の各関数はprototype属性を有し、Function.prototype.bind()を除いてプロトタイプを指す.
  • は、各オブジェクトに__proto__属性があり、オブジェクトを作成する構造関数のプロトタイプを指しています.実はこの属性は[[prototype]]を指していますが、[[prototype]]は内部的な属性ですので、_proto_を使ってアクセスすることはできません.
  • オブジェクトは、__proto__を介して当該オブジェクトに属さない属性を探し、__proto__はオブジェクトを接続してプロトタイプチェーンを構成することができる.
  • 7.相手のタイプをどう判断するか
  • は、Object.prototype.toString.call(xx)を通過することができる.これにより、[object Type]のような文字列が得られます.
  • instanceofは、オブジェクトのタイプを正確に判断することができます.内部メカニズムは、オブジェクトのプロトタイプチェーンにタイプがあるかどうかを判断するprototype
  • です.
    8.矢印関数の特徴
    function a() {
         
    	 return () => {
         
    		 return () => {
         
    			 console.log(this)
     }
     } }
    console.log(a()()())
    
    矢印関数は実はthisがないので、この関数の中のthisは彼の外面的全面的な第一個が矢印関数の関数のthisではないことに依存します.この例⼦では、aを使用して、前頁コードの中の第一の状況に合致するため、thisはwindowである.そして、this旦は上下⽂を結んでいます.コードの変更はありません.
    9.This
    function foo() {
         
    console.log(this.a) }
    var a = 1
    foo()
    var obj = {
          a: 2,
    foo: foo
    }
    obj.foo()
    //        `this`             ,                
    //            ,`this`       `c`  ,          `this`   
    var c = new foo() c.a = 3
    console.log(c.a)
    //         call,apply,bind    this,         new
    
    10.async、awaitの長所と短所
    asyncとawaitが直接Promiseを使用する場合、thenの使用チェーンを処理して、コードをより明確で正確に書くことができるのが強みです.欠点はawaitの濫用は性能問題を引き起こす可能性があります.awaitはコードをブロックするので、その後の非同期コードは前者に依存しないかもしれませんが、前者の完成を待つ必要があります.コードの合併性が失われました.
    下半身から見て、awaitを使用するコードの一つ.
    var a = 0
    var b = async () => {
         
     a = a + await 10
     console.log('2', a) // -> '2' 10
     a = (await 10) + a
     console.log('3', a) // -> '3' 20
    }b() a++
    console.log('1', a) // -> '1' 1
    
  • ⿰先関数bは先に行動し、await 10に到達する前に変数aはまだ0であったが、await内部でgeneratorsが実現され、generatorsはスタック中東⻄を保持するので、この時a=0は保存された.
  • は、awaitが非同期動作であるため、awaitに遭遇すると、146がpendingの状態のPromiseオブジェクトに戻り、一時的に執行コードの制御権に戻り、関数外のコードが継続的に実行されるようになるので、先に処理される.
  • この時点で同期コードの操作が完了し、非同期コードを実行し始め、保存した値を持ち出して使用する場合、a=10です.