вторник, 31 мая 2011 г.

__proto__ во всех браузерах

Ссылка "__proto__", как известно, указывает на прототип объекта в браузерах FireFox, Google Chrome и Safari. Обычно ссылку на прототип можно получить комбинацией ссылок constructor и prototype, но когда используется классическое для JavaScript наследование:
function A(){/*...*/};
function B(){/*...*/};
B.prototype = new A();
var b = new B();
, то в этом случае вызов
b.constructor.prototype
укажет на прототип конструктора A, а не на созданный объект конструктора A, который передан прототипу:
alert(b.constructor.prototype === A.prototype);//'true'
. Как же в этом случае можно обратиться именно к прототипу объекта b (естественно, не зная, каков его конструктор)? Можно переопределить ссылку constructor у объекта, созданного по конструктору A, указав ей на B:
B.prototype.constructor = B;
, но тогда мы потеряем возможность добраться до прототипа конструктора A, что может так же понадобиться.
Так что остаётся только ссылка "__proto__" - больше никак. Но этой ссылки нет в некоторых браузерах - например, в IE и в Opera`е.
Но если чего-то нету, то можно это недостающее создать самим. Для того, что бы всё заработало везде, надо вставить конструкцию
if (!this.hasOwnProperty('__proto__'))
    /** @type A */ this.__proto__ = arguments.callee.prototype;
внутрь нашего конструктора-наследничка. И тогда всё получится:
function A(){/*...*/};
function B() {
    /*...*/
    if (!this.hasOwnProperty('__proto__'))
        /** @type A */ this.__proto__ = arguments.callee.prototype;
};
B.prototype = new A();
var b = new B();
alert(b.__proto__ === B.prptotype);//'true'
alert(b.constructor.prototype === A.prototype);//'true'

Комментариев нет: