【问题标题】:Problems extending object in Javascript ECMA6在 Javascript ECMA6 中扩展对象的问题
【发布时间】:2017-06-02 22:46:54
【问题描述】:

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

学科类别:

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

【问题讨论】:

  • Object.assign() 方法仅将可枚举和拥有的属性从源对象复制到目标对象。” developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 鉴于 ES2015,我不明白您为什么不使用正确的 extends 关键字来创建子类。
  • 不是子类?是一个DOM元素对象,需要继承Subject类
  • 啊,你正试图将你的类mixin 到一个 DOM 类中?
  • 确实如此。我知道还有其他解决方案我只是想知道这是否可能。 :)

标签: javascript inheritance ecmascript-6 prototype


【解决方案1】:

Object.assign 仅将自己的可枚举属性从源对象复制到目标。您的Subject 对象只有一个自己的 属性: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;
}

...但这又快又脏,只是概念。请注意我是如何停在Object.prototype 而不是复制toString 之类的。


旁注:以您现在的方式扩展 DOM 元素会使您很容易与将来添加到 DOM 的方法或其他库等发生冲突。您可能对此很好,但这会让我担心。包装元素(就像 jQuery 一样)是我的偏好。

【讨论】:

    【解决方案2】:

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

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

    只需用 Subject 包装 dom-element 并与您的班级一起工作。

    【讨论】:

    • @T.J.Crowder,哎呀。删除了那部分。
    猜你喜欢
    • 1970-01-01
    • 2010-11-06
    • 2012-05-12
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-21
    相关资源
    最近更新 更多