2016-12-11 49 views
0

我有一個類designMain延伸designJavascript繼承與事件監聽

我發現,如果我在design,設置事件監聽,當事件被觸發,以this所有引用將僅指非擴展design對象。有沒有辦法克服我的擴展課程的這個缺點?

UPDATE - 我已經包括了ES6版本,預計其工作,並顯示什麼,我試圖完成 - 即this與擴展類總是引用擴展的類,即使內的代碼(例如的addEventListener)基類。在這種情況下,this.name應始終來自擴展類。

這裏是a jsFiddle

HTML

<div id="test"> 
    Design (click will fail) 
</div> 

<div id="test2"> 
    DesignMain (click will succeed) 
</div> 

的JavaScript

design = (function() { 
    function design() { 
    this.name = "design"; 

    var _this = this; 
    var e = document.getElementById("test"); 
    e.addEventListener("click", function() { 
     _this.callHello(); 
    }); 
    } 

    design.prototype.callHello = function() { 
    // I expect that this.name will be "designMain" 
    console.log(this.name) 
    // will fail if called from the design class eventListener 
    this.hello(); 
    } 

    return design; 
})(); 


designMain = (function() { 
    function designMain() { 
    this.name = "designMain"; 
    this.init(); 
    } 

    designMain.prototype.init = function() { 
    this.extend(); 
    var _this = this; 
    var e = document.getElementById("test2"); 
    e.addEventListener("click", function() { 
     _this.callHello(); 
    }); 
    } 

    designMain.prototype.extend = function() { 
    var old = new design(); 
    // save reference to original methods 
    this._designMain = Object.create(old); 
    for (var name in this._designMain) { 
     if (!this[name]) { 
     this[name] = this._designMain[name] 
     } 
    } 
    } 

    designMain.prototype.hello = function() { 
    alert("Hello " + this.name); 
    } 

    return designMain; 
})(); 


var t = new designMain(); 

使用ES6 - 它按預期工作(see fiddle

class design { 
    constructor() { 
    this.name = "design"; 

    var _this = this; 
    var e = document.getElementById("test"); 
    e.addEventListener("click", function() { 
     _this.callHello(); 
    }); 
    }; 

    callHello() { 
    // should be "designMain" 
    console.log(this.name) 
    this.hello(); 
    } 

    get name() { 
    return this._name; 
    }; 
    set name(name) { 
    this._name = name; 
    }; 
} 


class designMain extends design { 
    constructor() { 
    super(); 
    this.name = "designMain"; 
    var _this = this; 
    var e = document.getElementById("test2"); 
    e.addEventListener("click", function() { 
     _this.callHello(); 
    }); 
    }; 

    hello() { 
    alert("Hello " + this.name); 
    } 

} 

t = new designMain(); 
+0

我不明白這一點。你想'design'繼承'designMain'嗎?如果是的話,爲什麼你沒有做任何事情來實現呢?這個「擴展」方法應該做什麼? – Bergi

+0

你'ceate'方法(這應該是靜態的,順便說一句)已被棄用。只需使用Object.create'。 – Bergi

+0

@Bergi - 我已經更新與ES6版本,它的行爲與預期的問題 - 即designMain繼承擴展設計,所有提及'this'將designMain方法和屬性。我更新了我的代碼中使用的Object.create,並用靜態函數撥弄身邊,但沒能獲得'this'內與基地「類」生成的代碼更新。是否有可能在不使用ES6 Class方法的情況下模擬真正的類繼承? – mseifert

回答

0

感謝Bergi和他發佈的鏈接 - 我有一個解決方案。擴展/繼承使用Object.create方式簡單,我只需要添加design.call(this)運行的基類的構造函數。

designMain = (function() { 
    designMain.prototype = Object.create(design.prototype); 

    function designMain() { 
    design.call(this) 

工作液:

design = (function() { 
    function design() { 
    this.name = "design"; 

    var _this = this; 
    var e = document.getElementById("test"); 
    e.addEventListener("click", function() { 
     _this.callHello(); 
    }); 
    } 

    design.prototype.callHello = function() { 
    // will fail if called from the design class eventListener 
    console.log(this.name) 
    this.hello(); 
    } 

    return design; 
})(); 


designMain = (function() { 
    designMain.prototype = Object.create(design.prototype); 

    function designMain() { 
    design.call(this) 
    this.name = "designMain"; 
    this.init(); 
    } 

    designMain.prototype.init = function() { 
    var _this = this; 
    var e = document.getElementById("test2"); 
    e.addEventListener("click", function() { 
     _this.callHello(); 
    }); 
    } 

    designMain.prototype.hello = function() { 
    alert("Hello " + this.name); 
    } 

    return designMain; 
})(); 


var t = new designMain();