Javascript заставляет объекты отступать друг к другу - PullRequest
2 голосов
/ 10 мая 2010

Вот уродливый Javascript, было бы неплохо найти обходной путь.

В Javascript нет классов, и это хорошо. Но он реализует откат между объектами довольно уродливо. Основополагающей конструкцией должен быть один объект, который, когда свойство не может быть найдено, возвращается к другому объекту.

Итак, если мы хотим, чтобы a вернулся к b, мы бы хотели сделать что-то вроде:

a = {sun:1};
b = {dock:2};
a.__fallback__ = b;

1010 * тогда *

a.dock == 2;

Но вместо этого Javascript предоставляет оператор new и prototypes. Поэтому мы делаем гораздо менее элегантно:

function A(sun) {
   this.sun = sun;
};
A.prototype.dock = 2;
a = new A(1);

a.dock == 2;

Но помимо элегантности, это также строго менее мощно, потому что это означает, что все, что создано с помощью A, получает тот же запасной объект .

Я хотел бы освободить Javascript от этого искусственного ограничения и иметь возможность предоставить любому отдельному объекту любой другой отдельный объект в качестве его запасного варианта. Таким образом, я мог бы сохранить текущее поведение, когда оно имеет смысл, но использовать наследование на уровне объекта, когда это имеет смысл.

Мой первоначальный подход заключается в создании фиктивной функции конструктора:

function setFallback(from_obj, to_obj) {
    from_obj.constructor = function () {};
    from_obj.constructor.prototype = to_obj;
}

a = {sun:1};
b = {dock:2};
setFallback(a, b);

Но, к сожалению:

a.dock == undefined;

Любые идеи, почему это не работает, или какие-либо решения для реализации setFallback?

(я работаю на V8 через node.js, если это зависит от платформы)


Edit:

Ниже я опубликовал частичное решение, которое работает в случае с V8, но не является общим. Я все еще оценил бы более общее решение.

Ответы [ 2 ]

5 голосов
/ 10 мая 2010

Вы можете просто использовать Object.create.Он является частью ES5, поэтому он уже доступен в некоторых браузерах.Я считаю, что это именно то, что вы хотите.

0 голосов
/ 10 мая 2010

Хорошо, еще немного исследований и кроссплатформенной проверки, и есть еще немного информации (хотя это и не общее решение).

Некоторые реализации имеют в основном то, что я сделал для моего __fallback__. Он называется __proto__ и почти идеален:

a = {sun:1};
b = {dock:2};
a.__proto__ = b;

a.dock == 2;

Кажется, что то, что происходит при создании нового объекта, примерно таково:

a = new Constructor(...args...);

производит поведение, примерно эквивалентное:

object.constructor = constructor;
object.__proto__ = constructor.prototype;
constructor.call(this, ...args...);

Поэтому неудивительно, что последующее изменение и настройка конструктора объекта или constructor.prototype не даст никакого эффекта, поскольку настройка __proto__ уже установлена.

Теперь для моего приложения v8 я могу просто использовать __proto__, но я понимаю, что это не отображается на виртуальной машине IE (я не запускаю Windows, поэтому не могу сказать). Так что это не общее решение проблемы.

...