首頁  >  文章  >  web前端  >  關於JS 繼承的介紹

關於JS 繼承的介紹

不言
不言原創
2018-07-05 17:10:251498瀏覽

這篇文章主要介紹了關於JS 繼承的介紹,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

##ClassA

  • 由兩部分組成建構子和原型。

  • 建構子的部分,每個實例都是獨立的。

  • 原型的部分,每個實例是共享的。

  • // 构造函数
    function ClassA(sColor) {
        this.color = sColor;
    }
    
    // 原型
    ClassA.prototype.sayColor = function () {
        alert(this.color);
    };
產生一個實例

  • 內部操作:

  1. this 指向一個新{ }, 該物件的__proto__ 指向ClassA.prototype。

  2. 執行建構子 ClassA。

  3. 傳回 this 所指向的 { }。

var a = new ClassA();

console.log(a.__proto__ === ClassA.prototype);
// a 的继承对象指向 ClassA
console.log(a.constructor === ClassA);
原型部分的繼承

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 ,此時兩者共用一個this。
  1. 執行建構子 ClassA。
  2. 刪除暫時引入。
  3. function ClassB(sColor) {
        this.newMethod = ClassA;
        this.newMethod(sColor);
        delete this.newMethod;
    }
  4. 建構函式部分的繼承--apply/call/bind

    它是物件冒充的一種函式實作
  • 把ClassB 的this 綁定到ClassA 的this 上,執行建構子ClassA。
  • function ClassB(sColor) {
        ClassA.call(this, sColor);
        // 以下两种方式效果一样,只是实现方式不同
        // ClassA.apply(this, [sColor]);
        // ClassA.bind(this, sColor)();
    }
  • 繼承

    繼承由兩部分組成:建構子的繼承和原型的繼承。任意選擇繼承方式組合即可。
  • 建構子的原型中的屬性--constructor,永遠指向該建構函式本身。如果繼承時被修改,那麼在最後請修正。
  • 繼承是保留原來的特性,所以可以在繼承後,將新的建構子或原型屬性擴充。
  • Date 的繼承
// 需要考虑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中文網! 

相關推薦:

原生JS寫入Ajax的請求函數功能

以上是關於JS 繼承的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn