「javascript高級プログラム設計」学習ノート10.9-10.11.関数内部

10110 ワード

注目前端の民謡より多くのオリジナル技術記事を読む
関連コード→
10.9関数内部
  • ES 5には、関数内部に2つの特殊オブジェクトargumentsthis、1つの内部属性caller
  • ES 6新規new.target属性
  • 10.9.1アーグメンント
  • arguments関数を呼び出した時に入ってきたすべてのパラメータを含むクラスのオブジェクト
  • キーワード定義関数の場合のみfuncitonオブジェクト(矢印関数なし)
  • 対象は一つarguments属性であり、指し示すcallee所在関数の指針(関数ではなくポインタである関数名)
  • 厳格モードでアクセスargumentsエラー
  • //     :    
    function factorial(num) {
      if (num <= 1) return 1
      else return num * factorial(num - 1)
    }
    //   arguments.callee          
    function factorial(num) {
      if (num <= 1) return 1
      else return num * arguments.callee(num - 1) // callee  arguments      
    }
    
    let trueFactorial = factorial //        
    
    //   factorial  ,trueFactorial    
    factorial = function () {
      return 0
    }
    console.log(trueFactorial(5)) // 120,  arguments.callee               ,      
    console.log(factorial(5)) // 0,      
    10.9.2 this
  • 標準関数では、arguments.callee関数を指すコンテキストオブジェクト、すなわち関数が実行する環境オブジェクト(グローバルスコープthis)
  • window.color = 'red' // vscode node    ,        window,    window  global
    let o = { color: 'blue' }
    function sayColor() {
      console.log(this.color)
    }
    sayColor() // 'red',this      
    o.sayColor = sayColor
    o.sayColor() // 'blue',this    o
  • 矢印関数window定義関数のコンテキストオブジェクト、すなわちこの関数の外部の環境オブジェクト
  • let sayColor2 = () => {
      console.log(this.color) // this    sayColor2    ,     
    }
    sayColor2() // 'red',this      
    o.sayColor2 = sayColor2
    o.sayColor2() // 'red',this      
  • イベントコールやタイミングコールである関数を呼び出した場合this意図していないオブジェクトを指し、コールバック関数を矢印関数として書いて問題を解決することができる
  • function King() {
      this.royaltyName = 'Henry'
      setTimeout(() => {
        console.log(this.royaltyName) //     ,this          , King()      
      }, 1000)
    }
    function Queen() {
      this.royaltyName = 'Elizabeth'
      setTimeout(function () {
        console.log(this.royaltyName) //     ,this          , setTimeout()      
      }, 1000)
    }
    new King() // 'Henry',1    
    new Queen() // undefined,1    
    10.9.3 caller
  • ES 5は、this属性を定義し、現在の関数を呼び出す関数(グローバルスコープではnull)
  • function callerTest() {
      console.log(callerTest.caller)
    }
    callerTest() // null,         
    
    function outer() {
      inner()
    }
    function inner() {
      console.log(inner.caller)
    }
    outer() // [Function: outer], outer()  
    
    //     
    function inner() {
      console.log(arguments.callee.caller) // arguments.callee  arguments       , inner
    }
    outer() // [Function: outer], outer()  
  • callerの値はあくまでもarguments.callerの区別undefined関数のためのarguments.caller
  • 厳格モードでアクセスcaller関数であるarguments.caller属性割当値がエラー
  • function inner2() {
      console.log(arguments.caller) // undefined
      console.log(arguments.callee) // [Function: inner2]
    }
    inner2()
    10.9.4 new.target
  • ES 6が関数内部に追加caller属性を追加し、検出関数が使用されているかどうかnew.targetキーワードコール
  • 未使用new呼び出し、newの値はnew.target
  • 使用undefined呼び出し、newの値は呼び出しのコンストラクター
  • function King2() {
      if (!new.target) {
        console.log(new.target, 'King2 must be instantiated using "new"')
      } else {
        console.log(new.target, 'King2 instantiated using "new"')
      }
    }
    new King2() // [Function: King2] 'King2 instantiated using "new"'
    King2() // undefined 'King2 must be instantiated using "new"'
    10.10関数の属性と方法
  • 関数には2つの属性が含まれています.new.targetlength
  • prototype保存関数が受信したいネーミングパラメータの個数
  • function nameLength(name) {
      return name
    }
    function sumLength(sum1, sum2) {
      return sum1 + sum2
    }
    function helloLength() {
      return 'Hello'
    }
    console.log(nameLength.length, sumLength.length, helloLength.length) // 1 2 0
  • lengthポインティング関数のプロトタイプオブジェクト、保存関数のすべての例の方法は列挙できない(使用prototype発見できない)
  • console.log(Array.prototype) //        Array     ,  sort()   
    console.log(Object.keys(Array)) // [],Array              
    console.log(Object.getOwnPropertyNames(Array)) // [ 'length', 'name', 'prototype', 'isArray', 'from', 'of' ],Array           
  • 関数には3つの方法があります.for-inapply()
    function sumPrototype(num1, num2) {
      return num1 + num2
    }
  • call()bind()いずれも指定apply()値呼び出し関数であり、呼び出し関数を設定する際の関数体内call()の指向
  • this2つのパラメータを受信する:①運転関数のスコープ(thisを指定)②パラメータ配列(例またはargmentsオブジェクトでも可)
  • function applySum1(num1, num2) {
      return sum.apply(this, arguments) //   arguments  
    }
    function applySum2(num1, num2) {
      return sum.apply(this, [num1, num2]) //       
    }
    console.log(applySum1(10, 10)) // 20
    console.log(applySum2(10, 10)) // 20
  • this幾つかのパラメータを受信する:①運転関数の作用域(thisを指定する);残りのパラメータは1つずつ入ってくる
  • function callSum(num1, num2) {
      return sum.call(this, num1, num2) //         
    }
    console.log(callSum(10, 10)) // 20
  • apply()call()本当に強大なところは、関数運転の役割領域を拡張できること、すなわち制御関数体内apply()
  • window.color = 'red' // vscode node    ,        window,    window  global
    let o2 = { color: 'blue' }
    function sayColor3() {
      console.log(this.color)
    }
    sayColor3() // 'red',this      
    sayColor3.call(this) // 'red',this      
    sayColor3.call(window) // 'red',this      ,    window  global
    sayColor3.call(o2) // 'blue',this    o2
  • call()関数のプロトタイプthis方法利用Function.prototype.apply.call()バインディング(経由apply簡略コード)
  • let f1 = function () {
      console.log(arguments[0] + this.mark)
    }
    let o3 = {
      mark: 95,
    }
    f1([15]) // '15undefined',this  f1      ,this.mark undefined
    f1.apply(o3, [15]) // 110, f1 this   o3
    Function.prototype.apply.call(f1, o3, [15]) // 110,  f1      apply  ,  call    
    Reflect.apply(f1, o3, [15]) // 110,                   ,    (    、   this  、    )
  • call()新しい関数例を作成し、そのReflect.apply()転送bind()の対象
  • に結び付けられている.
    let o4 = { color: 'blue' }
    function sayColor4() {
      console.log(this.color)
    }
    let bindSayColor = sayColor4.bind(o4) //     bindSayColor, this    o4
    sayColor4() // 'red',this      
    bindSayColor() // 'blue',this      o4
    10.11関数式
  • 関数宣言の重要な特徴は、関数宣言の向上であり、すなわち関数声明がコード実行前に定義されること
  • sayHi() // 'Hi',      
    function sayHi() {
      console.log('Hi')
    }
  • 関数式は、先に値を付けてから使用し、匿名関数を作成する必要があります(this識別子がない).
  • 匿名関数のbind()属性は空の文字列
  • sayHi2() // ReferenceError: Cannot access 'sayHi2' before initialization,        
    let sayHi2 = function sayHi() {
      console.log('Hi')
    }
  • 関数宣言と関数表現の違いは、関数宣言の使用を条件ブロックで避け、関数式
  • let condition = false
    if (condition) {
      function sayHi3() {
        console.log('true')
      }
    } else {
      function sayHi3() {
        console.log('false')
      }
    }
    sayHi3() //           ,             
    
    let sayHi4
    if (condition) {
      sayHi4 = function () {
        console.log('true')
      }
    } else {
      sayHi4 = function () {
        console.log('false')
      }
    }
    sayHi4() // false,              
  • 関数を作成し、変数に値を割り当てることで、他の関数を1つの関数の値として返すことができる
  • /**
     *          object key,      
     * @param {String} key     key
     * @param {String} sort   /  :asc/desc,   asc
     */
    function arraySort(key, sort) {
      return function (a, b) {
        if (sort === 'asc' || sort === undefined || sort === '') {
          //   :a[key] > b[key]
          if (a[key] > b[key]) return 1
          else if (a[key] < b[key]) return -1
          else return 0
        } else if (sort === 'desc') {
          //   :a[key] < b[key]
          if (a[key] < b[key]) return 1
          else if (a[key] > b[key]) return -1
          else return 0
        }
      }
    }
    var userList = [
      { name: 'Tony', id: 3 },
      { name: 'Tom', id: 2 },
      { name: 'Jack', id: 5 },
    ]
    console.log(userList.sort(arraySort('id'))) // [{ name: 'Tom', id: 2 },{ name: 'Tony', id: 3 },{ name: 'Jack', id: 5 }],  id     
    console.log(userList.sort(arraySort('id', 'desc'))) // [{ name: 'Jack', id: 5 },{ name: 'Tony', id: 3 },{ name: 'Tom', id: 2 }],  id     
    console.log(userList.sort(arraySort('name'))) // [{ name: 'Jack', id: 5 },{ name: 'Tom', id: 2 },{ name: 'Tony', id: 3 }],  name     
    まとめ&質問
  • argmentsとは何ですか?argments.calleeはどこを指しますか?関数名と関数論理が結合されている階乗関数
  • thisの標準関数と矢印関数の指向はどう違いますか?イベントのコールバックやタイミングのコールバックでは、なぜ矢印関数がより適切なのですか?
  • 関数のcaler属性はどこを指していますか?argments.callerの値は何ですか?厳格なモードではどのような制限がありますか?
  • new.targetの役割と値はそれぞれ何ですか?
  • 関数にはどのような属性がありますか?指差と使い方はそれぞれ何ですか?
  • 関数のスコープをコードで証明してください.Funtions.prototype.apply.call()、bind()はどのように関数のスコープを拡張し、Function.prototype.apple.call()の意味を説明してください.
  • 関数宣言と関数表現の最大の違いは何ですか?どのように声明のアップグレードを理解しますか?
  • コードを書いて、対象配列のある対象属性に従って並べ替えて、パラメータによって並べ替え属性と昇順