2017-01-18 15 views
1

ECMA6内の別のオブジェクトでオブジェクトを拡張する際に問題が発生しています。問題のオブジェクトを拡張した後、更新されたオブジェクトでメソッドを見つけることができないと言います。ここに私のコードは次のとおりです。Javascriptでオブジェクトを拡張する際の問題ECMA6

Subjectクラス:

// Subject to be observed 
class Subject { 
    constructor() { 
     this.observers = new ObserverList(); 
    } 

    addObserver(observer) { 
     this.observers.add(observer); 
    } 

    removeObserver(observer) { 
     this.observers.removeAt(this.observers.indexOf(observer, 0)); 
    } 

    notify(context) { 
     for(let i = 0; i < this.observers.count(); i++) { 
      this.observers.get(i).update(context); 
     } 
    } 
} 

、オブジェクトが拡張され、私のコード:

/** 
* Function to extend an object with another object 
*/ 
function extend(obj, extension) { 
    Object.assign(obj, extension); 
} 

// Get our DOM elements 
let controlCheckbox = document.getElementById("mainCheckbox"), 
    addBtn = document.getElementById("addNewObserver"), 
    container = document.getElementById("observersContainer"); 


// Concrete subject 
// extend controlling checkbox with Subject class 
extend(controlCheckbox, new Subject()); 

// Clicking the checkbox will trigger notifications to it's observers 
controlCheckbox.onclick =() => { 
    controlCheckbox.notify(controlCheckbox.checked); 
}; 

addBtn.onclick = addNewObserver; 

function addNewObserver() { 
    let check = document.createElement('input'); 
    check.type = 'checkbox'; 

    extend(check, new Observer()); 
    check.update = function(value) { 
     this.checked = value; 
    }; 
    controlCheckbox.addObserver(check); 
    container.appendChild(check); 
} 

onclickが発射された場合、方法controlCheckbox.addObserverが定義されていないことを言っています。 controlCheckboxオブジェクトを表示するためにブレークポイントを追加しました。そのメソッドがプロトタイプで使用可能であることがわかります。これはうまくいかないでしょうか?私が間違っているところを誰かが指摘できますか?

+0

* "Object.assign()メソッドは、列挙可能なプロパティと独自のプロパティをソースオブジェクトからターゲットオブジェクトにのみコピーします。" * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign –

+2

ES2015では、なぜサブクラスを作成するために適切な 'extends'キーワードを使用していないのか分かりません。 – Alnitak

+1

サブクラスではありませんか? Subjectクラスを継承する必要があるDOM要素オブジェクトです – devoncrazylegs

答えて

1

Object.assign独自のソースオブジェクトからターゲットへの列挙可能なプロパティのみをコピーします。 Subjectオブジェクトには独自のプロパティが1つしかありません:observers他のすべてのメソッド(メソッド)は継承されており、「所有している」ことはありません。

継承されたプロパティを処理する独自のバージョンのextendを作成する必要があります。

その他の問題点は、デフォルトではメソッドも列挙できないため、単純なfor-inはそれらを見つけることができないということです。 getOwnPropertyNamesgetPrototypeOfを使用する必要があります。例えば

function extend(target, ...sources) { 
    for (const source of sources) { 
     for (let obj = source; obj && obj !== Object.prototype; obj = Object.getPrototypeOf(obj)) { 
      for (const name of Object.getOwnPropertyNames(obj)) { 
       if (!(name in target)) { 
        target[name] = obj[name]; 
       } 
      } 
     } 
    } 
    return target; 
} 

...それは、単にコンセプトは非常に迅速かつ汚いです。私はtoStringなどをコピーするのではなく、Object.prototypeにどのように止まったのかに注意してください。


サイドノート:あなたが将来的にDOMに追加されたメソッドとの競合にかなり開いたまま、または他のライブラリなどにより、あなたはそれで罰金かもしれないが、それある方法でDOM要素を拡張私を心配するだろう。 jQueryのような要素を折り返すことが私の好みです。

0

いいえ、Object.assignはprotoから何もコピーしません。

console.log(Object.assign({}, Object.create({x:9})).x)

だけSubjectでDOM要素をラップしたクラスで動作します。

+0

@ T.J.Crowder、ooops。その部分を削除しました。 – Qwertiy

関連する問題