JS赤皮書解読の高級関数

3903 ワード

一、安全なタイプの検出typeof、instance ofは、あるオブジェクトが元のオブジェクトなのかそれともカスタムのオブジェクトなのかを検出します.Object元のString()メソッドで検出することができます.
(1)元の配列を検出する
    function isArray(value) {
      return Object.prototype.toString.call(value)==='[object Array]'
    }
(2)原生関数の検出
    function isFunction(value) {
      return Object.prototype.toString.call(value)==='[object Function]'
    }
(3)検出原生正則表現
    function isRegExp(value) {
      return Object.prototype.toString.call(value)==='[object RegExp]'
    }
原理:Object原生のtoStringメソッドを呼び出すと、いずれも「object NativeContstruct Name」形式の文字列を返します.Aray、Object、Functionなどの内部はすべて[クラス]の属性で、この属性はNativeControuctoNameの具体的な名前を指定しました.Object、Aray、RegExp、Functなどです.
これにより、元のJSオブジェクトかどうかを判断することができます.
二、作用域の安全な構造関数の注意:構造関数はnewで呼び出される関数です.
    function Person(name,age,sex){
      this.name=name
      this.age=age
      this.sex=sex
    }
new後は新規作成対象となります.thisとはこの新規オブジェクト(新例)のことです.
    let personA=new Person("a",'18','man')
    console.log(personA,window.name,window.age,window.sex) //{age:"18",name:"a",sex:"man"}
newを使わない後の結果はwindowでPersonの構造関数を呼び出して、Personの内部のthisがwindowなことを指すことを招いて、name、age、sexもすべてwindowの属性です.
    let personB=Person("b",'22','woman')
    console.log(personB,window.name,window.age,window.sex) //undefined "b" "22" "woman"
そのため、コンストラクタを呼び出すには、そのスコープを判断する必要があります.
解決方法:まず、thisオブジェクトが正しいタイプの例であることを確認し、そうでない場合は、新しいインスタンスを作成して返します.
    function Person(name,age,sex){
      // instanceof xxx   
      if(this instanceof Person){
        this.name=name
        this.age=age
        this.sex=sex
      }else{
        return new Person(name,age,sex)
      }
    } 
欠陥:構造関数を使用した盗撮モードxx.call(this.xxx)は、プロトタイプチェーンを使用しないと、この継承を破壊します.
    function Father(age){
      if(this instanceof Father){
        this.age=age
      }else{
        return new Father(age)
      }
    }

    function Child(sex) {
      //  Child  Father     (this instanceof Father false),
      //        Father  
      //           Child    
      Father.call(this,18)
      //this  Child
      //  Father    (this instanceof Father),
      // Father  this.age this    Child 
      this.sex=sex
    }

    let childA=new Child('man')
    console.log(childA.age) //undefined
簡単に言えば、ChildはFatherの属性を呼び出した時に、新しく作成されたFatherの例であり、thisはChild自身のthisではない.
解決:プロトタイプチェーンを使う
    ...
    ...
    ...
    // Child     Father   
    Child.prototype=new Father()
    let childA=new Child('man')
    console.log(childA.age) //18
三、不活性性のロード(最適化プロジェクト)はif文を毎回実行する必要がない、すなわち不活性性のロードはなぜですか?if文があるので、if文がないより遅くなります.
    function  createFamily(number){
      if(number===1){
       //xxxx1
      }else{
        if(number===2){
          //xxxx2
        }else{
          //xxxx3
        }
      }
    }
最初の最適化:
    function  createFamily(number){
      if(number===1){
        createFamily=function () {
          //xxxx1
        }
      }else{
        if(number===2){
          createFamily=function () {
            //xxxx2
          }
        }else{
          createFamily=function () {
            //xxxx3
          }
        }
      }
    }
第二の最適化:
    let createFamily=(function(number) {
      if(number===1){
        return function () {
          //xxxx1
        }
      }else{
        if(number===2){
          return function () {
            //xxxx2
          }
        }else{
          return function () {
            //xxxx3
          }
        }
      }
    //     number    
    })(number)
注意:どちらに行くかを初めて判断する場合にのみ使用します.往復切り替えの判定条件には適用されません.次の呼び出しは直接判断しないで、そちらに行きます.これはプロジェクトコードの最適化に使用できます.
(終わり)