在Javascript ECMA6中扩展对象的问题

时间:2017-01-18 13:59:58

标签: javascript inheritance ecmascript-6 prototype

我在使用ECMA6中的另一个对象扩展对象时遇到问题。在我扩展了有问题的对象后,它说它无法在更新的对象上找到该方法。这是我的代码:

学科班:

RealizePalette

我扩展对象的代码:

// 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对象,我可以看到该方法在原型中可用。这应该不起作用吗?谁能指出我哪里出错?

2 个答案:

答案 0 :(得分:1)

Object.assign仅将自己的可枚举属性从源对象复制到目标。您的Subject对象只有一个拥有的属性:observers。所有其他(方法)都是继承的,而不是&#34;拥有&#34;。

如果您希望将这些属性复制到目标,您还需要编写自己的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;
}

......但那是非常快速和肮脏的,只是概念。请注意我是如何停在Object.prototype而不是复制toString等。

附注:以你离开的方式扩展DOM元素,你会对将来添加到DOM或其​​他库等方法的方法产生冲突。你可能会很好,但它会让我担心。包装元素(比如jQuery)会是我的首选。

答案 1 :(得分:0)

不,Object.assign不会复制proto中的任何内容。

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

只需用Subject包裹dom-element并与你一起工作。