Комментарии 44
Это моя первая статья на хабре
+18
Кстати, для желающих реально разобраться в теме — очень рекомендую почитать ветку комментов от dsCode:
habrahabr.ru/post/111393/#comment_3555912
Начиная с «В ECMAScript нет (пока) сахара для классов».
Очень классно и познавательно. Там можно и разобраться, что такое __proto__, prototype и new на нормальных, понятных примерах.
habrahabr.ru/post/111393/#comment_3555912
Начиная с «В ECMAScript нет (пока) сахара для классов».
Очень классно и познавательно. Там можно и разобраться, что такое __proto__, prototype и new на нормальных, понятных примерах.
+1
В консоли Хрома:
т.е.
> function Test(){} var q=new Test(); console.log(q.constructor.prototype===q.__proto__);
true
т.е.
__proto__
равно constructor.prototype
?+2
А как это на практике можно использовать?
0
Вы про __proto__?
Ну например если в переопределенном методе какого либо класса вам нужно вызвать этод же метод родительского, тогда можете сделать так:
Object.getPrototypeOf(this).myMethod.apply(this, arguments);
Ну например если в переопределенном методе какого либо класса вам нужно вызвать этод же метод родительского, тогда можете сделать так:
Object.getPrototypeOf(this).myMethod.apply(this, arguments);
+2
Неверно. Данный подход зациклится при использовании сложных иерархий (начиная с трех уровней) — можете проверить.
Пусть иерархия выглядит так:
var a = {};
var b = Object.create(a);
var c = Object.create(b);
a.name = «a»;
b.name = «b»;
c.name = «c»;
b.some_func = function() { console.log(Object.getPrototypeOf(this).name); }
c.some_func(); // выведет b, т.е. нам не удалось получить a как прототип this
Пусть иерархия выглядит так:
var a = {};
var b = Object.create(a);
var c = Object.create(b);
a.name = «a»;
b.name = «b»;
c.name = «c»;
b.some_func = function() { console.log(Object.getPrototypeOf(this).name); }
c.some_func(); // выведет b, т.е. нам не удалось получить a как прототип this
0
так все же верно,c inherits b inherits a, вызов c::parent вернет b, вызов c::parent::parent вернет 'a'.
0
Хорошо, вот другой пример.
var a = {};
var b = Object.create(a);
var c = Object.create(b);
a.some_func = function() { console.log(«a»); }
b.some_func = function() { console.log(«b»); Object.getPrototypeOf(this).some_func.apply(this, arguments); }
c.some_func = function() { console.log(«c»); Object.getPrototypeOf(this).some_func.apply(this, arguments); }
a.some_func(); //a
b.some_func(); //b a
c.some_func(); //c b b b b…
Это я к чему? Да к тому, что конструкция Object.getPrototypeOf(this).myMethod.apply(this, arguments); делает нечто, совершенно отличающиеся от вызова родительского метода.
var a = {};
var b = Object.create(a);
var c = Object.create(b);
a.some_func = function() { console.log(«a»); }
b.some_func = function() { console.log(«b»); Object.getPrototypeOf(this).some_func.apply(this, arguments); }
c.some_func = function() { console.log(«c»); Object.getPrototypeOf(this).some_func.apply(this, arguments); }
a.some_func(); //a
b.some_func(); //b a
c.some_func(); //c b b b b…
Это я к чему? Да к тому, что конструкция Object.getPrototypeOf(this).myMethod.apply(this, arguments); делает нечто, совершенно отличающиеся от вызова родительского метода.
+1
Угу, получается надо юзать Object.getPrototypeOf(this).some_func.apply(Object.getPrototypeOf(this), arguments);?
0
Для метода, не меняющего состояние объекта — пойдет.
Если метод меняет состояние, то первым аргументом apply может быть только this.
Для решения данной проблемы надо вспомнить, что вообще-то мы знаем, от какого объекта унаследовались. То есть правильный вариант таков:
var a = {};
var b = Object.create(a);
var c = Object.create(b);
a.some_func = function() { console.log(«a»); }
b.some_func = function() { console.log(«b»); a.some_func.apply(this, arguments); }
c.some_func = function() { console.log(«c»); b.some_func.apply(this, arguments); }
a.some_func(); //a
b.some_func(); //b a
c.some_func(); //c b a
На случай неизвестной заранее иерархии или для дополнительной защиты, можно накрутить что-нибудь с замыканиями.
Но Object.getPrototypeOf(this) использовать для подобной цели нельзя.
Если метод меняет состояние, то первым аргументом apply может быть только this.
Для решения данной проблемы надо вспомнить, что вообще-то мы знаем, от какого объекта унаследовались. То есть правильный вариант таков:
var a = {};
var b = Object.create(a);
var c = Object.create(b);
a.some_func = function() { console.log(«a»); }
b.some_func = function() { console.log(«b»); a.some_func.apply(this, arguments); }
c.some_func = function() { console.log(«c»); b.some_func.apply(this, arguments); }
a.some_func(); //a
b.some_func(); //b a
c.some_func(); //c b a
На случай неизвестной заранее иерархии или для дополнительной защиты, можно накрутить что-нибудь с замыканиями.
Но Object.getPrototypeOf(this) использовать для подобной цели нельзя.
+1
>поиск происходит в другом объекте, свойстве __proto__
>оно [свойство prototype] по умолчанию является объектом
Такие формулировки вводят в заблуждение. Свойство __proto__ не содержит никаких объектов, оно содержит ссылку на объект. Это важно.
>поиск происходит в другом объекте, на который ссылается свойство __proto__
>оно [свойство prototype] по умолчанию ссылается на объект
>оно [свойство prototype] по умолчанию является объектом
Такие формулировки вводят в заблуждение. Свойство __proto__ не содержит никаких объектов, оно содержит ссылку на объект. Это важно.
>поиск происходит в другом объекте, на который ссылается свойство __proto__
>оно [свойство prototype] по умолчанию ссылается на объект
0
Мне вот только одно не понятно, почему вы не поискали подобные темы на хабре, имхо уже топиков 20 обсудало эту тему.
habrahabr.ru/post/108915/
habrahabr.ru/post/133034/
habrahabr.ru/post/120193/
И таких тем еще куча, тема очередной дубль своими словами о том что уже давно написали, разжевали.
habrahabr.ru/post/108915/
habrahabr.ru/post/133034/
habrahabr.ru/post/120193/
И таких тем еще куча, тема очередной дубль своими словами о том что уже давно написали, разжевали.
+6
Да ладно Вам, никто из читающих не будет искать, а так хоть узнаю что-то новое.
0
Искал. Но так и не нашел простого и понятного объяснения свойства __proto__.
Вы хотите сказать что статья эта никому не нужна, и лучше бы ее не было?
Однако уже больше сотни человек добавили ее в избранное.
Вы хотите сказать что статья эта никому не нужна, и лучше бы ее не было?
Однако уже больше сотни человек добавили ее в избранное.
+1
Но так и не нашел простого и понятного объяснения свойства __proto__.
Вы мне напомнили этот комикс:
0
Русская версия, на всяк случай:
0
я же не стандарт предлагаю, а просто хочу помочь некоторым людям разобраться в javascript
0
Расшифрую)
— Ситуация: есть 14 разных топиков, объясняющих __proto__ просто и понятно
— 14?! Долбануться! Нужно написать один универсальный топик, объясняющий __proto__ реально просто и понятно
— Ситуация: есть 15 разных топиков, объясняющих __proto__ просто и понятно
— Ситуация: есть 14 разных топиков, объясняющих __proto__ просто и понятно
— 14?! Долбануться! Нужно написать один универсальный топик, объясняющий __proto__ реально просто и понятно
— Ситуация: есть 15 разных топиков, объясняющих __proto__ просто и понятно
0
ну и в чем зло 15го топика?
0
Мне кажется чем больше литературы по определенной теме, тем лучше — есть выбор.
+1
Если рекомендуете для старых браузеров эмулировать функции `Object.create` и `Object.getPrototypeOf`, то, лучше уж, давайте ссылку на
github.com/kriskowal/es5-shim — тут эти методы описаны максимально по стандарту и учитывают очень много разных нюансов.
Например: функция `Object.create` задаёт свойство `__proto__` у созданного объекта, а в функция `Object.getPrototypeOf` несколько универсальные приведённого вами кода:
github.com/kriskowal/es5-shim — тут эти методы описаны максимально по стандарту и учитывают очень много разных нюансов.
Например: функция `Object.create` задаёт свойство `__proto__` у созданного объекта, а в функция `Object.getPrototypeOf` несколько универсальные приведённого вами кода:
Object.getPrototypeOf = function getPrototypeOf(object) {
return object.__proto__ || (
object.constructor
? object.constructor.prototype
: prototypeOfObject
);
};
+2
Как корректно поменять __proto__ объекта, чтобы превратить его в массив (серверный JS)? Такой код работает:
Но вы говорите, что использовать его некорректно. Есть ли какой-нибудь корректный способ без копирования элементов массива?
a.__proto__=Array.prototype
Но вы говорите, что использовать его некорректно. Есть ли какой-нибудь корректный способ без копирования элементов массива?
0
var MyArray = function () {};
MyArray.prototype = new Array();
var a = new MyArray();
// same as
// var a = {};
// a.__proto__=Array.prototype
a.push(42);
console.log(a.length); // 1
Если просто копировать аттрибуты прототипа массивы, то сломается length
0
А разве не надо ещё и конструктор прототипу прописать?
MyArray.prototype.constructor = MyArray;
А то получится, что конструктор у нас будет системным массивом, а не нашей функцией.
MyArray.prototype.constructor = MyArray;
А то получится, что конструктор у нас будет системным массивом, а не нашей функцией.
0
Основная проблема такого подхода вот в чём:
var MyArray = function () {};
MyArray.prototype = new Array();
var a = new MyArray();
a[1] = 123;
a.length; // 0
0
Таким образом, вы сделали массив из пустого объекта. А если имеется объект типа
И такой подход точно работает (неправильно отрабатывает конструкция типа
Есть ли способ проделать то же самое, не трогая свойство __proto__?
{0:'x', 1:'y'}
, то его можно превратить в «почти-массив» таким кодом:obj.__proto__ = Array.prototype;
obj.length = <длина массива>; // Допустим, в нашей задаче она известна
И такой подход точно работает (неправильно отрабатывает конструкция типа
for (var i in obj)
, но ее можно заменить методами forEach и т. д. Есть ли способ проделать то же самое, не трогая свойство __proto__?
0
Эта конструкция всегда неправильно работает:
То, что вы хотите — можно сделать так:
Но если вас интересует теоретическая возможность, то я думаю, что кроссбраузерно и стандартно — это врядли реально.
for (var i in obj)
.То, что вы хотите — можно сделать так:
var obj = {0:'x', 1:'y'};
obj.length = 2;
console.log( [].slice.call(obj) ); // ['x', 'y' ]
Но если вас интересует теоретическая возможность, то я думаю, что кроссбраузерно и стандартно — это врядли реально.
0
Метод slice копирует элементы массива и создает новый массив. Соответственно, тратятся ресурсы на ненужную операцию.
А кроссбраузерность не нужна — речь шла о серверном JS. На клиенте можно было бы, например, воспользоваться методом jQuery.makeArray (который работает примерно так же, как предложенный вами вариант).
Вообщем, пока я решил проблему хаком указанным выше, правильного варианта, по-видимому, не существует.
А кроссбраузерность не нужна — речь шла о серверном JS. На клиенте можно было бы, например, воспользоваться методом jQuery.makeArray (который работает примерно так же, как предложенный вами вариант).
Вообщем, пока я решил проблему хаком указанным выше, правильного варианта, по-видимому, не существует.
0
Поставил плюс, но, пожалуйста, в следующий раз выбирайте тему, не обсосаную 200 раз.
+5
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Prototype, proto и оператор new