jslang求職シリーズ-11-手書きnew


ディレクトリ
振り回さない先端は、塩魚とどう違いますか?
目次
ディレクトリ
二言前言
三原生new
四手書きnew
4.1簡単実現;
4.2完備バージョン;
二言前言
目次に戻ります
面接官:手書きでnewを作ってください.
この問題を見たら、慌てないでください.jslangさんはゆっくりとあなたを連れてやります.
まず一つのケースを見ます.
this.name = 'jsliang';
let Foo = function() {
  this.name = 'zhazhaliang';
}
let foo = new Foo();
console.log(foo.name); //    ?
console.log(window.name); //    ?
上のコードは何を出力しますか?
答えは:
  • zhazhaliang
  • jsliang
  • では、この問題のnewは何をしましたか?私たちは深く研究します.
    三原生new
    目次に戻ります
    まず原生newの一例を見て、newに何ができるかを考えてみます.
    function Person( name, age){
      this.name = name;
      this.age = age;
     
      // return;                              //    this
      // return null;                         //    this
      // return this;                         //    this
      // return false;                        //    this
      // return 'hello world';                //    this
      // return 2;                            //    this
      
      // return [];                           //        [], person.name = undefined
      // return function(){};                 //        function,   this, person.name = undefined
      // return new Boolean(false);           //        boolean,   this, person.name = undefined
      // return new String('hello world');    //        string,   this, person.name = undefined
      // return new Number(32);               //       number,   this, person.name = undefined
    }
    
    var person = new Person("jsliang", 25);
    console.log(person); // Person {name: "jsliang", age: 25}
    四手書きnew
    目次に戻りますnewの内容を理解し始めました.どうやって手書きしたらいいですか?
    4.1簡単実現
    目次に戻ります
    まず簡単に3行のコードでnewを書いてみます.
  • は、最初に空のオブジェクトnewを作成する.
  • は次いでtempObj = {}方法を呼び出し、Foo.applytempObj方法のパラメータとして使用し、applyの実行コンテキスト作成時には、Foothisオブジェクトを指す.
  • は次いでtempObj関数を実行し、このときのFoo関数実行コンテキストのFoothisオブジェクトを指す.
  • は最後にtempObjオブジェクトを返します.
  • function myNew(func, ...args) {
      const tempObj = {};
      func.apply(tempObj, args);
      return tempObj;
    }
    
    this.name = 'jsliang';
    let Foo = function(name, age) {
      this.name = name;
      this.age = age;
    }
    let foo = myNew(Foo, 'zhazhaliang', 25);
    console.log(foo.name); //    ?
    console.log(foo.age); //    ?
    console.log(window.name); //    ?
    上記のように、tempObjthisに属し、tempObjに結合されていることが分かります.
  • foo
  • zhazhaliang
  • 25
  • wow、開豁ではありませんか?簡単なjsliangの実現は3行のコードだけが必要です.
    4.2完備バージョン
    目次に戻ります
    OKです.簡単版を書きました.複雑版に必要な条件を見てみましょう.
  • の最初のパラメータは、関数である必要があります.newですが、オリジナルのものは作れません.const person = new Person()になります.
  • プロトタイプチェーン継承.const person = myNew(Person)objは、objのプロトタイプ__proto__、すなわちfuncを指すオブジェクトを新たに作った.
  • は、prototypeの指向を修正する.obj.__proto__ === func.prototypeによってthisapplyとを結合し、パラメータを配列として伝達する(方法体定義は、残りのパラメータを配列に分解した)
  • .
  • は、構造関数がobjまたはfuncに戻るかどうかを判断する.Objectは、Functiontypeofを排除する必要があると判断した.
  • 非関数およびオブジェクトは、新たに作成されたオブジェクトを返します.そうでなければ、コンストラクションのobject値を返します.
  • 最終的な実現:
    function myNew(func, ...args) {
      // 1.      
      if (typeof func !== 'function') {
        throw '           ';
      }
    
      // 2.      
      const obj = {};
    
      // 3.       __proto__    func         
      //              (constructor.prototype)         
      obj.__proto__ = Object.create(func.prototype);
    
      //      IE       2      3   
      // const obj = Object.create(func.prototype);
    
      // 4.    apply    this             
      let result = func.apply(obj, args);
      
      // 5.                   ,         
      //          obj
      const isObject = typeof result === 'object' && result !== null;
      const isFunction = typeof result === 'function';
      return isObject || isFunction ? result : obj;
    }
    
    //   
    function Person(name) {
      this.name = name;
      return function() { //       5  
        console.log('        ');
      };
    }
    //       2     3  
    Person.prototype.sayName = function() {
      console.log(`My name is ${this.name}`);
    }
    const me = myNew(Person, 'jsliang'); //       4  
    me.sayName(); // My name is jsliang
    console.log(me); // Person {name: 'jsliang'}
    
    //       1  
    // const you = myNew({ name: 'jsliang' }, 'jsliang'); //   :           
    このように、私達はnullがどんなものかを知っています.手書きtypeof null === objectに触れると、慌てません.
    jslangの文書庫は
    高く険しい山採用
    知識共有署名-非商業的使用-同じ方法で4.0国際許諾協議を共有する。は許可を行う.ベース
    https://github.com/LiangJunrong/document-library上の作品.本許諾契約の授権以外の使用権限は、
    https://creativecommons.org/licenses/by-nc-sa/2.5/cn/で獲得した.