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)

unclechu 12.04.2012 19:44

Обращение к приватной переменной из прототипной функции
 
Доброго времени суток! Подскажите, никак не могу найти решение касательно js. Давайте сразу к простому примеру:
var human = (function () {
	var prototype = {}
	prototype.getName

	prototype.getName = function (str) {
		if (str) this.name = str
		return this.name
	}

	function constructor(data) {
		this.name
	}
	constructor.prototype = prototype
	return constructor
}())

var h1 = new human
h1.getName('Vasia')
var h2 = new human
h2.getName('Petia')

Условие тут таково, что должны быть прототипные функции, которые будут обращаться в приватным переменным экземпляра конструктора.
В данном случае this.name — это публичное свойство, но что если я не хочу чтобы можно было напрямую менять name в духе:
var h1 = new human
h1.getName('Vasia')
h1.name = 'Petia'

Как мне это преградить? Иными словами: как работать с приватными переменными из функции в прототипе? Вроде как банальная потребность.
Единственное что пришло в голову: это хранить массив id экземпляров с объектами данных выше уровнем, чем конструктор, а в this.id хранить уже сам идентификатор конкретного экземпляра. Но, согласитесь, это маразм, да и к тому же поменять id многого ли стоит?

Раед 12.04.2012 20:10

Цитата:

Сообщение от unclechu
как работать с приватными переменными из функции в прототипе

Цитата:

Сообщение от nasqad
надо новое замыкание создавать

может так
var human = (function () {
    var prototype = {}
    prototype.getName
   
    +function(){
   var name;
    prototype.getName = function (str) {
        if (str) name = str
        return name
    }
 
    function constructor(data) {
        name
    }
   }()
    constructor.prototype = prototype
    return constructor
}())
 
var h1 = new human
h1.getName('Vasia')
var h2 = new human
h2.getName('Petia')

unclechu 12.04.2012 20:14

Цитата:

Сообщение от Раед (Сообщение 168618)
как обычно, через замыкание
var human = (function () {
    var name;
    var prototype = {}
    prototype.getName
 
    prototype.getName = function (str) {
        if (str) name = str
        return name
    }
 
    function constructor(data) {
        name
    }
    constructor.prototype = prototype
    return constructor
}())
 
var h1 = new human
h1.getName('Vasia')
var h2 = new human
h2.getName('Petia')

И каков по вашему результат?
Если бы всё было так просто, я бы не спрашивал, после выполнения этого кода, стало так:
h1.getName() // Petia
h2.getName() // Petia

Мне нужно чтобы name был уникальным для каждого экземпляра.

Раед 12.04.2012 20:26

Цитата:

Сообщение от unclechu
как работать с приватными переменными из функции в прототипе

Цитата:

Сообщение от nasqad
надо новое замыкание создавать

может так
var human = (function () {
    var prototype = {}
    prototype.getName
   
    +function(){
   var name;
    prototype.getName = function (str) {
        if (str) name = str
        return name
    }
 
    function constructor(data) {
        name
    }
   }()
    constructor.prototype = prototype
    return constructor
}())
 
var h1 = new human
h1.getName('Vasia')
var h2 = new human
h2.getName('Petia')

Mixxx 12.04.2012 20:32

Исправил вашь код:
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

Раед 12.04.2012 21:14

Цитата:

Сообщение от Mixxx
Вашь код не работает в IE9 и Опере

ну это понятно. так должен заработать
var human = (function () {
    var prototype = {}
    prototype.getName
    
    +function(){
   var name;
    prototype.getName = function (str) {
        if (str) name = str
        return name
    }
  
    function constructor(data) {
        name
    }
   }()
    constructor.prototype = prototype
    return constructor
}())
  
var h1 = new (human())();
h1.getName('Vasia')
var h2 = new (human())();
h2.getName('Petia')

Цитата:

Сообщение от Mixxx
что за синтаксис такой +function

а Это для вызова на месте. вместо скобок.

Octane 12.04.2012 21:26

Просто назовите свойство _name. Такое соглашение о именование свойств, которые не должны использоваться снаружи, давно устоялось, известно и используется множеством js-программистов.

Mixxx 12.04.2012 21:47

Цитата:

а Это для вызова на месте. вместо скобок.
Не знал что так можно
Цитата:

Сообщение от Раед
ну это понятно. так должен заработать

Всеравно не работает ни в ие ни в опере
Опера например ругается
Цитата:

Uncaught exception: TypeError: 'human()' is not a constructor
Цитата:

Сообщение от Octane (Сообщение 168645)
Просто назовите свойство _name.

_name слишком скромно, лучше назвать $_$___$nAMe тогда точно никто его не изменит :D

Раед 12.04.2012 22:54

Цитата:

Сообщение от Mixxx
лучше назвать $_$___$nAMe

не, лучше так: ['аопл уыркШГЦР ЦЫЕАП \n\n kdgnrjk \trnga 58456g563&*^*&^$%^$(\']

Octane 12.04.2012 23:17

Ну городите замыкания, раз вас веселит соглашение об именовании свойств, которое, как UpperCamelCase для конструкторов и lowerCamelCase для всего остального, присутствует в guidеline\'ах к стилю JavaScript-кода.


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