Список вопросов
Как зайти в Даркнет?!
25th January, 01:11
5
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Синтаксис ООП в js и использование prototype
Просмотров: 342
 
Ответов: 5
Чем отличаются данные куски кода и какой в каких случаях будет предпочтительнее?
A
function Obj() {}
Obj.method = function(type) {
return this.coords[type];
};
var obj = new Obj(),
current = obj.method(type);
B
function Obj() {}
Obj.prototype.method = function(type) {
return this.coords[type];
};
var obj = new Obj(),
current = obj.method(type);
C
var obj = {
method : function(type) {
return this.coords[type];
}
},
current = obj.method(type);
D
function objMethod(type){
return this.coords[type];
}
var obj = {
method : objMethod
},
current = obj.method(type);
added @ 1732:
E
function Obj() {
this.method = function(type) {
return this.coords[type];
};
}
var obj = new Obj(),
current = obj.method(type);
function Obj() {}
Obj.method = function(type) {
return this.coords[type];
};
var obj = new Obj(),
current = obj.method(type);
function Obj() {}
Obj.prototype.method = function(type) {
return this.coords[type];
};
var obj = new Obj(),
current = obj.method(type);
var obj = {
method : function(type) {
return this.coords[type];
}
},
current = obj.method(type);
function objMethod(type){
return this.coords[type];
}
var obj = {
method : objMethod
},
current = obj.method(type);
function Obj() {
this.method = function(type) {
return this.coords[type];
};
}
var obj = new Obj(),
current = obj.method(type);
JS — объектно-ориентированный язык, но в нем отсутствуют классы, их заменяют конструкторы объектов, поэтому вместо обычного наследования через классы существует наследование через прототипы. Т.е. экземпляр класса наследует его свойства и методы, которые находятся в его прототипе.
Конструктор класса (function Obj() {}) — функция, в которой описаны свойства и методы прототипа, поэтому ко всем ним будет доступ при создании экземпляра.
В примере A конструктор пустой, а Obj.method присваивает метод объекту, а не его прототипу, поэтому он не будет наследован в obj = new Obj(). Этот пример не работает.
Пример B — правильный, здесь метод method добавляется в прототип и будет наследоваться всеми экземплярами.
Пример C чаще всего используется, когда нужно реализовать singleton или namespace, потому что это простой хэш без конструктора, его нельзя наследовать. Фактически это не объект в ООП понимании, а просто ассоциативный массив, в котором могут содержаться любые данные, методы и другие объекты.
Пример D аналогичен примеру C, только его свойство method содержит ссылку на внешнюю функцию. Этот пример можно использовать, когда нужно вызвать какую-то функцию из внешней библиотеки.
Пример E правильный и аналогичен примеру B, с разницей в том, что наследуемый метод задается сразу в конструкторе, а не через prototype.
Ну на самом деле разница между B и E есть, в случае E, когда метод объявляется прямо в конструкторе он будет иметь доступ к приватным переменным и методам, это так называемые привилегированные методы, а вот в примере B нет возможности работать с приватными данными.
Вот о чем я говорю:
var MyClass = function() {
// Приватные атрибуты
var _a, _b;
// Приватный метод
function _myPrivate(isbn) {
}
// публичный привилегированный метод
this.MyPublicPlus = function() {
};
}
// публичный непривилегированный метод.
MyClass.prototype = {
MyPublic: function() {
}
};
Метод MyPublicPlus будет иметь доступ к _a, _b и _myPrivate(), а MyPublic нет…
var MyClass = function() {
// Приватные атрибуты
var _a, _b;
// Приватный метод
function _myPrivate(isbn) {
}
// публичный привилегированный метод
this.MyPublicPlus = function() {
};
}
// публичный непривилегированный метод.
MyClass.prototype = {
MyPublic: function() {
}
};
Вообще, всем кто интересуется тем, как устроен Javascript, советую прочесть www.crockford.com/javascript/javascript.html
В примере E еще стоит обратить внимание на слово this, которое означает, что method будет добавлен в прототип.
Если его не использовать, можно создавать private-свойства и методы, которые будут доступны из других методов экзмепляра, но не напрямую.
function Obj() {
var privateMethod = function(x) {
return x;
}
this.publicMethod = function(x) {
return privateMethod(x);
}
}
var obj = new Obj();
obj.privateMethod(1); // -> вызовет ошибку
obj.publicMethod(1); // -> вернет '1'
function Obj() {
var privateMethod = function(x) {
return x;
}
this.publicMethod = function(x) {
return privateMethod(x);
}
}
var obj = new Obj();
obj.privateMethod(1); // -> вызовет ошибку
obj.publicMethod(1); // -> вернет '1'
A, B, E — имеется конструктор Obj. в случае вызова функции через new — конструктор будет работать с новым объектом, в случае вызова через call/apply будет расширять заданный Вами объект. т.е. одна функция может быть и «классом» и «примесью».
C, D — создание объекта «руками», без конструктора. в D функция вынесена и проименована — подразумевается, что её можно использовать не только как метод.
B — используется прототипирование. прототип есть у каждого объекта*, это значит, что непримитивные типы данных (функции, массивы, даты, объекты) будут храниться только в прототипе, экономя память и время «создания» объекта, но замедляя последующую работу с объектом из-за того, что обращение к «общим» данным/методам будет происходить через (цепочку) прототипов.
A — функция тоже является объектом, и «метод» обозначен именно у объекта функции. объект функции(-конструктора) никак не связан с изменяемыми ею объектами. объет конструктора — хорошее место для всякого хлама, который не хочется распространять на все его «экземпляры».
пара моментов, которые следует осознать:
function Obj() {}
Obj.prototype.q = [1,2,3];
var obj = new Obj();
Obj.prototype.q[1] = 8;
alert(obj.q +" - "+ Obj.prototype.q); // 1,8,3 - 1,8,3
function Obj() {
this.val = 5;
this.method = function() { alert(this.val *2); };
};
var obj = new Obj();
window.setTimeout(obj.method, 1); // NaN
почитать:
ru.wikipedia.org/wiki/Прототипное_программирование
* dklab.ru/chicken/nablas/40.html — .constructor.prototype; где-то там же было объяснение необходимости ставить conctructor прототипа в «текущий» класс
www.webreference.com/js/column26/apply.html — apply-примесь
так же рекомендую погуглить про всякие typeof, instanceof, hasOwnProperty, isPrototypeOf, etc.
в какой пропорции использовать прототипы, замыкания, примеси и прочие декораторы — дело исключительно Вашего стиля.
function Obj() {}
Obj.prototype.q = [1,2,3];
var obj = new Obj();
Obj.prototype.q[1] = 8;
alert(obj.q +" - "+ Obj.prototype.q); // 1,8,3 - 1,8,3
function Obj() {
this.val = 5;
this.method = function() { alert(this.val *2); };
};
var obj = new Obj();
window.setTimeout(obj.method, 1); // NaN
Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться