我在使用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
对象,我可以看到该方法在原型中可用。这应该不起作用吗?谁能指出我哪里出错?
答案 0 :(得分:1)
Object.assign
仅将自己的可枚举属性从源对象复制到目标。您的Subject
对象只有一个拥有的属性:observers
。所有其他(方法)都是继承的,而不是&#34;拥有&#34;。
如果您希望将这些属性复制到目标,您还需要编写自己的extend
版本来处理继承的属性。
另一个问题是,默认情况下,您的方法也不会被枚举,因此只需一个简单的for-in
即可找到它们。您需要使用getOwnPropertyNames
和getPrototypeOf
。
例如:
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并与你一起工作。