Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Обращение к приватной переменной из прототипной функции (https://javascript.ru/forum/misc/27432-obrashhenie-k-privatnojj-peremennojj-iz-prototipnojj-funkcii.html)

GuardCat 12.04.2012 23:44

Кроме огорода замыканий не вижу вариантов. Можно, например, создавать в конструкторе одноимённое прототипному свойство, которое будет вызывать функцию с тем же именем. из прототипа, передавая ей приватную переменную. Саму процедуру обёртывания и замыкания можно тоже в прототип переместить. Так в конструкторе повторы будут, конечно, но меньше, чем если просто там размещать все функции. Получается как-то так:
function Human(name) {
	this.makeWrap("getName", [name]);
}

Human.prototype = {
	makeWrap:  function (propertyName, args) {
		this[propertyName] = (
			function(args) {
				return function() {
					return Human.prototype[propertyName](args);
				}
			}
		)(args)
	},
	getName: function(name) {
		return name[0];
	},
	constructor: Human
}
 
h1 = new Human("Василий Иванович");
h2 = new Human("Иван Васильевич");

alert(h1.getName())
alert(h2.getName())
. Как-то костыльно, nein? Вариант с соглашением проще. и лучше, на мой взгляд.

Mixxx 13.04.2012 00:02

Цитата:

Сообщение от GuardCat (Сообщение 168677)
Вариант с соглашением проще. и лучше, на мой взгляд.

Конечно проще, я его и юзаю всегда. Только если человек спросил как сделать как бы "приватную" переменную зачем его отговаривать? Он же не просто так спросил. Значит ему так надо. Коллеги, давайте уже наконец доверять друг другу :D

unclechu 13.04.2012 00:31

Цитата:

Сообщение от Mixxx (Сообщение 168628)
Исправил вашь код:
function log(a){document.body.innerHTML+=a+'<br>'}

//функция хуман это не конструктор, она возвращает конструктор которы надо потом инициализировать с помощью new
var human = (function () {
	var prototype = {}
	//prototype.getName
	var _data, _name;
	
	prototype.setName = function (str)
	{
		if (str) _name = str
	}
	prototype.getName = function () 
	{
		return _name
	}

	function constructor(data) {
		//this.name
                       _data=data

	}
	constructor.prototype = prototype
	return constructor
})

var Alfa = new (human())() //столько скобок нужно что бы new относилось к constructor а не к human, 

Alfa.setName('Vasia')
log('Alfa: '+ Alfa.getName() )

var Beta = new (human())()
Beta.setName('Petia')
Beta._name='Евгений Ваганыч'; //создаться публичное свойство _name но приватное _name не изменится
log('Beta: '+ Beta.getName() );

log('Alfa: '+ Alfa.getName() )



Раед,
Вашь код не работает в IE9 и Опере (в других не тестил)
опера ругается Uncaught exception: TypeError: 'h1.getName' is not a function
И я не понимаю что за синтаксис такой +function

Это конечно решение, но я так понимаю смысл использование прототипов теряется? Потому как: Alfa.__proto__ !== Beta.__proto__ Ну то-бишь не реюзится отсылка к прототипу уже, а попросту новые прототипы?

В таком случае решение с символом «_» — лучший вариант, когда нужны тру-прототипы.

Mixxx 13.04.2012 01:23

GuardCat,
Посмотрел вашь код
понял что вы предлагаете запоминать name в массиве который зависнет как параметр анонимной функции внутри нового метода getName который переопределит makeWrap. Надо сказать это весьма и весьма хиро%опо :D
setName можно реализовать также как в конструкторе:
...
	setName: function(newName)
	{
		this.makeWrap('getName',[newName])
	},
...

Но ведь это ужасно :( получается прямого доступа к полю нейм нету даже внутри методов объекта.

Во что у меня получилось из вашего кода (массивы убрал так как тут они не нужны):
function log(a){alert(a)}

function Human(name) 
{
	this.makeWrap("getName", name);
}

Human.prototype = 
{
	makeWrap:  function (propertyName, args) 
	{
		
		this[propertyName] = 
		(
			function(args) 
			{
				return function() 
				{
					return Human.prototype[propertyName](args);
				}
			}
		)(args)

	},
	setName: function(newName)
	{
		this.makeWrap('getName',newName)
	},
	getName: function(name) 
	{
		return name;
	},
	setLastName: function(LName)
	{
		this.makeWrap('getLastName',LName)
	},
	getLastName: function(LName)
	{
		return LName
	},
	getFullName: function()
	{
		return this.getName()+' '+this.getLastName();
	}

//	,constructor: Human
}
 
h1 = new Human("Владимир");
h2 = new Human("Дмитрий");
h1.setLastName('Путин');
log(h1.getFullName())

h2.setLastName('Медведев');
log(h2.getFullName())

h2.setName('Александр')
log(h2.getFullName())

log('Протипы равны? '+(h1.__proto__ === h2.__proto__))

GuardCat 13.04.2012 07:07

Mixxx, массивы будут удобны, если возникнет необходимость передавать больше одного параметра. Можно и в этом случае обойтись без массивов, но с ними проще.

unclechu 13.04.2012 14:55

Maxmaxmахimus, спасибо за ссылку, есть кое что полезное на заметку.

unclechu 13.04.2012 15:16

Приваты, судя по ECMA будут, и как я понял это будет private и объект x.
private key
x.key // x для приватов вместо this


Часовой пояс GMT +3, время: 05:05.