JavaScript: 今回は新しい演算子について完全に理解しました!

coldplay.xixi
リリース: 2020-09-27 17:30:37
転載
1638 人が閲覧しました

JavaScript: 今回は新しい演算子について完全に理解しました!

まえがき

JavaScript を学習する過程で、new 演算子に遭遇することは避けられません。よく見て、理解と記憶を深めてください。

新しい演算子とは何ですか?

new 演算子は、mdn で次のように定義されます。

new 演算子は、ユーザー定義のオブジェクト タイプまたは組み込みオブジェクトのインスタンスを作成します。コンストラクターインスタンス。

この文では、キーワード にはコンストラクターがある を見てみましょう。これはどういう意味ですか?まず、いくつかの例を見てみましょう。

//例1let Animal1=function(){this.name=1};let animal=new Animal1; //这里不带()相当于不传参数//=>Animal1 {name: 1}//例2let TestObj={}let t1=new TestObj;//=>Uncaught TypeError: TestObj is not a constructor复制代码
ログイン後にコピー

例 1 では、new ステートメントが正常に実行され、インスタンスが作成されたことがわかります。例 2 では、エラー TypeError: TestObj is not aconstructor in new a {} object が報告され、ターゲットが constructor## ではないことを示しています。 #。通常のオブジェクトでは new 演算子を実行できないのはなぜですか? ECMA 仕様には関連する導入部分があります:

If Type(argument) is not Object, return false.

If argument has a
[[Construct]] Internalメソッドは true を返します。 false を返します。

# 意味:

    #コンストラクターは最初にオブジェクトである必要があります。それ以外の場合は、条件が満たされません
  • #第二に、オブジェクトをコンストラクターとして使用するには、その前に
  • [[Construct]]
  • 内部メソッドが必要です 私たちの
  • {}
ここに 1 つのオブジェクトが最初の条件を満たす場合、それは明らかに

{} に内部メソッド [[Construct]] がないためであるに違いありません。したがって、new 演算子は構築時に使用できません。 ということで、new

演算子の操作可能なオブジェクトがわかったので、その機能を見てもいいでしょうか?答えはいいえだ!別の例を見てみましょう:

//例3let testObj={
    Fn(){        console.log("构造成功!")
    }
}let t3=new testObj.Fn;//=>Uncaught TypeError: testObj.Fn is not a constructor复制代码
ログイン後にコピー
what? 先ほど正常に構築された関数がメソッドとして機能しないのはなぜでしょうか?実際、これは MDN にも直接導入されています:

メソッドをコンストラクターにすることはできません! インスタンス化しようとすると、TypeError がスローされます。

は、 ## を意味します。 #methods コンストラクター

にすることはできません。メソッドのインスタンスを作成しようとすると、型エラーがスローされます。これを言うのは理にかなっていますが、まだ終わっていません。この文では原理が完全に説明されていません。別の例を見てみましょう:
//例4const example = {  Fn: function() { console.log(this); },  Arrow: () => { console.log(this); },
  Shorthand() { console.log(this); }
};new example.Fn();        // Fn {}new example.Arrow();     // Uncaught TypeError: example.Arrow is not a constructornew example.Shorthand(); // Uncaught TypeError: example.Shorthand is not a constructor复制代码
ログイン後にコピー

この例とは対照的に、ECMA 仕様をチェックインしたところ、すべての関数がIn FunctionCreateFunction:

FunctionCreate (kind, ParameterList, Body, Scope, Strict,prototype)

プロトタイプ引数がそうでなかった場合に依存します渡された場合、プロトタイプを組み込みオブジェクト %FunctionPrototype% にします。

「kind」が Normal でない場合は、allocKind を「非コンストラクター」にします。
  1. 定義この関数の

は、型

Normal
    の関数が作成された場合にのみ構築可能な関数であり、それ以外の場合は構築できないことがわかります。
  • この例では、Arrow
  • のタイプは
Arrow

ShortHand のタイプは です。したがって、Method は構築可能な関数ではありません。これは、例 3 で「メソッドはコンストラクターとして使用できない」と述べていることの説明にもなります。 new 演算子が操作できるターゲットを把握したら、ようやくその機能を明確な頭で見ることができます (TAT は簡単ではありません)。 新しいオペレーターは何を実装しますか? 関数を詳しく見るために簡単な例を見てみましょう:

function Animal(name){    this.name=name;    console.log("create animal");
}let animal=new Animal("大黄");  //create animalconsole.log(animal.name);       //大黄Animal.prototype.say=function(){    console.log("myName is:"+this.name);
}
animal.say();                   //myName is:大黄复制代码
ログイン後にコピー

この例から分析しましょう. まず、この文を見てみましょう:

let animal=new Animal("大黄");复制代码
ログイン後にコピー

したがって、

new

演算子を実行すると、

animal

オブジェクトが取得されます。その後、new 演算子がオブジェクトを作成し、これを変換する必要があることがわかります。オブジェクトが返されます。 。このコードをもう一度見てください: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">function Animal(name){ this.name=name; console.log(&quot;create animal&quot;); }复制代码</pre><div class="contentsignin">ログイン後にコピー</div></div>同時に、結果が表示されます。create Animal が実際に出力され、

Animal

関数本体が実行されたことがわかります。このプロセス中にパラメータが同時に渡されたため、出力ステートメントが実行されました。しかし、文 this.name=name は関数本体のどこにあるのでしょうか?これは文です: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">console.log(animal.name); //大黄复制代码</pre><div class="contentsignin">ログイン後にコピー</div></div>関数本体を実行すると、返されたオブジェクトの name 値が

this

に割り当てた値であることがわかります。このプロセス中、this の値は新しく作成されたオブジェクトを指します。最後に別の段落があります: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">Animal.prototype.say=function(){ console.log(&quot;myName is:&quot;+this.name); } animal.say(); //myName is:大黄复制代码</pre><div class="contentsignin">ログイン後にコピー</div></div>animal オブジェクトは

Animal

関数プロトタイプのメソッドを呼び出し、Animalanimalオブジェクトのプロトタイプチェーン上で、それはどの層にありますか?検証しましょう: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">animal.__proto__===Animal.prototype; //true复制代码</pre><div class="contentsignin">ログイン後にコピー</div></div> これで、 animal

__proto__

Animalprototype を直接指していることがわかります。 さらに、コンストラクターの関数本体で値を返すと、何が起こるか見てみましょう: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">function Animal(name){ this.name=name; return 1; }new Animal(&quot;test&quot;); //Animal {name: &quot;test&quot;}复制代码</pre><div class="contentsignin">ログイン後にコピー</div></div><p>可以看到,直接无视了返回值,那我们返回一个对象试试:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">function Animal(name){ this.name=name; return {}; }new Animal(&quot;test&quot;); //{}复制代码</pre><div class="contentsignin">ログイン後にコピー</div></div><p>我们发现返回的实例对象被我们的返回值覆盖了,到这里大致了解了<code>new操作符的核心功能,我们做一个小结。

小结

new操作符的作用:

  • 创建一个新对象,将this绑定到新创建的对象
  • 使用传入的参数调用构造函数
  • 将创建的对象的_proto__指向构造函数的prototype
  • 如果构造函数没有显式返回一个对象,则返回创建的新对象,否则返回显式返回的对象(如上文的{}

模拟实现一个new操作符

说了这么多理论的,最后我们亲自动手来实现一个new操作符吧~

var _myNew = function (constructor, ...args) {    // 1. 创建一个新对象obj
    const obj = {};    //2. 将this绑定到新对象上,并使用传入的参数调用函数

    //这里是为了拿到第一个参数,就是传入的构造函数
    // let constructor = Array.prototype.shift.call(arguments);
    //绑定this的同时调用函数,...将参数展开传入
    let res = constructor.call(obj, ...args)

    //3. 将创建的对象的_proto__指向构造函数的prototype
    obj.__proto__ = constructor.prototype

    //4. 根据显示返回的值判断最终返回结果
    return res instanceof Object ? res : obj;
}复制代码
ログイン後にコピー

上面是比较好理解的版本,我们可以简化一下得到下面这个版本:

function _new(fn, ...arg) {    const obj = Object.create(fn.prototype);    const res = fn.apply(obj, arg);    return res instanceof Object ? res : obj;复制代码
ログイン後にコピー

大功告成!

总结

本文从定义出发,探索了new操作符的作用目标和原理,并模拟实现了核心功能。其实模拟实现一个new操作符不难,更重要的还是去理解这个过程,明白其中的原理。

更多相关免费学习推荐:javascript(视频)

以上がJavaScript: 今回は新しい演算子について完全に理解しました!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:juejin.im
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!