JS継承の概要

不言
不言オリジナル
2018-07-05 17:10:251583ブラウズ

この記事では主に JS 継承の導入を紹介します。これは、必要な友人に参考にしていただけるようにしました。

コンストラクターの部分、各インスタンスは独立しています。
  • プロトタイプ部分は各インスタンスで共有されます。
  • // 构造函数
    function ClassA(sColor) {
        this.color = sColor;
    }
    
    // 原型
    ClassA.prototype.sayColor = function () {
        alert(this.color);
    };

    インスタンスを生成します
  • 内部操作:

    thisは新しい{ }を指し、オブジェクトの__proto__はClassA.prototypeを指します。
  • コンストラクターClassAを実行します。
  1. this が指す { } を返します。
  2. var a = new ClassA();
    
    console.log(a.__proto__ === ClassA.prototype);
    // a 的继承对象指向 ClassA
    console.log(a.constructor === ClassA);
  3. プロトタイプ部分の継承
  4. function ClassB() {
        // 实现继承 ClassA 构造函数部分的继承
    }
    
    ClassB.prototype = new ClassA();
    // ClassB.prototype 指向新对象时,原有的 ClassB.constructor 属性会消失。
    // new ClassA().hasOwnProperty('constructor') 为 false,新生成的对象无 constructor 属性。
    // 在此修复这个问题。
    ClassB.constructor = ClassB;
    // 不过还存在 new ClassA().hasOwnProperty('color') 为 true 问题
    // 实现继承 ClassA 构造函数部分的继承,生成的属性优先级比 new ClassA().color 高,顾可以忽略

    コンストラクター部分の継承 - オブジェクト偽装

ClassA を ClassB にメソッドとして導入し、この時点で 2 つは 1 つを共有します。

コンストラクターClassAを実行します。
  1. 一時的な紹介文を削除します。
  2. function ClassB(sColor) {
        this.newMethod = ClassA;
        this.newMethod(sColor);
        delete this.newMethod;
    }

    コンストラクタ部分の継承--apply/call/bind
  3. オブジェクト偽装の関数実装です

ClassBのthisとClassAのthisをバインドし、コンストラクタ ClassA を実行します。
  • function ClassB(sColor) {
        ClassA.call(this, sColor);
        // 以下两种方式效果一样,只是实现方式不同
        // ClassA.apply(this, [sColor]);
        // ClassA.bind(this, sColor)();
    }

    継承
  • 継承は、コンストラクターの継承とプロトタイプの継承の 2 つの部分で構成されます。継承方法は任意に組み合わせて選択できます。

コンストラクターのプロトタイプ内の属性 --constructor は、常にコンストラクター自体を指します。継承時に修正した場合は、最後に修正してください。
  • 継承では元の機能が保持されるため、継承後に新しいコンストラクターやプロトタイプのプロパティを拡張できます。
  • 日付継承
  • // 需要考虑polyfill情况
    Object.setPrototypeOf = Object.setPrototypeOf ||
        function(obj, proto) {
            obj.__proto__ = proto;
            return obj;
        };
    /**
     * 用了点技巧的继承,实际上返回的是Date对象
     */
    function MyDate() {
        // bind属于Function.prototype,接收的参数是:object, param1, params2...
        var dateInst = new(Function.prototype.bind.apply(Date, [null].concat(Array.prototype.slice.call(arguments))))();
        // 更改原型指向,否则无法调用MyDate原型上的方法
        // ES6方案中,这里就是[[prototype]]这个隐式原型对象,在没有标准以前就是__proto__
        Object.setPrototypeOf(dateInst, MyDate.prototype);
        dateInst.abc = 1;
        return dateInst;
    }
    // 原型重新指回Date,否则根本无法算是继承
    Object.setPrototypeOf(MyDate.prototype, Date.prototype);
    MyDate.prototype.getTest = function getTest() {
        return this.getTime();
    };
    let date = new MyDate();
    // 正常输出,譬如1515638988725
    console.log(date.getTest());
    // 继承的重点语句
    var dateInst = new(Function.prototype.bind.apply(Date, [null].concat(Array.prototype.slice.call(arguments))))();
    // 使用经典方法实现继承的时候,由于 Date 是内部对象,使用上有限制
    // 提示 “this is not a Date object”
    // 说明 Date 上的方法只能由 Date 的实例调用,它会识别内部的 [[class]],浏览器无法修改。
    // 所以想到了如下方案
    var dateInst = new Date(...arguments);
    // 能实现构造函数的只有 bind
    var dateInst = new (Date.bind(null, ...arguments))();
    // ES5下无法实现 ...,只能转成数组
    [null].concat(Array.prototype.slice.call(arguments));
    // 参数中带数组的只有 ayyly
    var dateInst = new (Function.prototype.bind.apply(Date, [null].concat(Array.prototype.slice.call(arguments))))();
  • 以上がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

    関連する推奨事項:

ネイティブ JS で Ajax リクエスト関数を作成する

以上がJS継承の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。