Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   При вызове локальной функции объекта не могу использовать свойства объекта (https://javascript.ru/forum/misc/64975-pri-vyzove-lokalnojj-funkcii-obekta-ne-mogu-ispolzovat-svojjstva-obekta.html)

Gudsaf 17.09.2016 13:17

При вызове локальной функции объекта не могу использовать свойства объекта
 
Суть: не могу использовать свойства объекта в локальных функциях объекта.
Красноречивый пример:
var ball = new ball(a,b,c,d);

function ball (A,B,C,D){
    this.a = A;
    this.b = B;
    this.c = C;
    this.size = calcSize(D)

    function calcSize(diameter){
        return (a+b)*c*diameter; // a,b,c = undefined!
    }
}


Как сделать чтобы переменные a, b, c были видны в локальной функции calcSize(D)?

рони 17.09.2016 15:20

Gudsaf,
var ball = new ball(1,2,3,4);

function ball (A,B,C,D){
    this.a = A;
    this.b = B;
    this.c = C;
    this.size = calcSize.bind(this)(D)

    function calcSize(diameter){
        return (this.a+this.b)*this.c*diameter;     }
}
 alert(ball.size);

может
var ball = new ball(1,2,3,4);

function ball (A,B,C,D){
    this.a = A;
    this.b = B;
    this.c = C;
    this.size = calcSize(D)

    function calcSize(diameter){
        return (A+B)*C*diameter;
    }
}
 alert(ball.size);

warren buffet 17.09.2016 18:23

Вот так

var ball = new ball(a,b,c,d);

function ball (A,B,C,D){
    this.a = A;
    this.b = B;
    this.c = C;
    this.size = (A+B)*C*D;
}


Зачем тебе функция как метод, если она фактически constructor?

warren buffet 17.09.2016 18:25

Цитата:

Сообщение от рони
может

Не может, а так. Просто идти на поводу у них нельзя. Они и не такое еще придумают. Лол.

Gudsaf 17.09.2016 19:05

Цитата:

Сообщение от warren buffet (Сообщение 428966)
Зачем тебе функция как метод, если она фактически constructor?

Проблема немного в другом.
Я пытаюсь освоить ООП в JS на боевом примере, и хочется сделать красиво, но не очень выходит.

Я проектирую два (по сути как) класса:
- график (GraphStruct)
- кривая (CurveStruct)

График имеет свои свойства и методы:
function GraphStruct(distCrvs, maxCurveLength, maxCurveHeight, ..., jsonData){

		this.mainNumOfPnts = calcAveregeNum(jsonData);
		this.numberOfCurves = jsonData.lessons.length;
		this.distanceBtwCurves = distCrvs;
		this.maxWidth = maxCurveLength;
		this.maxHeight = maxCurveHeight;
		this.denstyKfcnt = denstyKfcnt;
		this.roundKfcnt = roundKfcnt;
		this.ratBasToTechKfcnt = ratBasToTechKfcnt;
		this.graphObjects = {
			curves: [],
			axisAndGrids: undefined,
			relationships: undefined
		};

		// рассчитываем параметры всех точек графика исходя из настроек графика
		this.calcCurvesParam = function (Data) {

			var arr = [];
			// пробегаем все кривые  описанные в JSON, шлём параметры графика через this
			for(var i= 0; Data.lessons[i]; i++){
				this.graphObjects.curves.push(new CurveStruct( i, Data.lessons[i]));
			}
			return arr;
		};

		function calcAveregeNum (jsonData){
			...
		}

		...
	}

Кривая имеет свои свойства и методы:
function CurveStruct(curveNumber, jsonLesson) {

		if ( this.__proto__ != graph ) { 
			inherit(graph, this); } //наследовать свойства графика в кривую

		this.curveNumber = curveNumber;
		this.numberOfPoints = jsonLesson.test_results.length;
		this.midPointNumber = calcMidPoint(this.numberOfPoints);
		this.position_x = calcPosX(this);
		this.curveObjects = {
			lines: [],
			planes: [],
			points: []
		};
		
		// куча методов которые используют значения свойств
		// объекта graph, то есть: 
		// - mainNumOfPnts
		// - distanceBtwCurves
		// - denstyKfcnt
		// - и др...
		// 
		// я хочу их вызывать в конструкторе кривых и его методах
		// просто и изящно, на подобие этого (кстати так и вызываю сейчас): 
		function calcPosX (curve) {
			var crvNumber = curve.curveNumber;
			var crvAll = curve.numberOfCurves;
			var midCurve = Math.floor(crvAll/2);
			return curve.distanceBtwCurves * (crvNumber - midCurve));
		}

	}

Как видите, чтобы в методах кривой я мог использовать свойства графика просто и красиво, я делаю прототипное наследование: указываю прототипом кривой объект графика. У меня получается использовать свойства графика только тогда, когда:
  1. объект графика инициализирован

Когда он не инициализирован, я получаю в значениях наследуемых параметров undefined

Логика в том, что по приходу JSON'а я хочу тупо вызовом конструктора графика, сразу же выстроить и сам график и заодно все кривые, которые строятся своим конструктором (данные для графика и кривых лежат в самом JSON). Но сейчас я сначала делаю объект графика, а потом уже рассчитываю все кривые, потому что если вызвать конструктор кривой во время процесса инициализации объекта графика - будет наследование undefined значений. То есть выглядит это так:
var graph = new GraphStruct(40, 800, 350, 1, 0.82, 9/10, dataInput); // создал график graph
		graph.calcCurvesParam(dataInput); // вызвал конструктор кривых и создал кривые в графике graph


А в идеале хотелось бы так:
var graph = new GraphStruct(40, 800, 350, 1, 0.82, 9/10, dataInput);
		// без вызова calcCurvesParam(dataInput)


Соответственно вызов конструктора кривой перенести в конструктор графика, как-то так:
function GraphStruct(distCrvs, maxCurveLength, maxCurveHeight, ..., jsonData){

		this.mainNumOfPnts = calcAveregeNum(jsonData);
		this.numberOfCurves = jsonData.lessons.length;
		this.distanceBtwCurves = distCrvs;
		this.maxWidth = maxCurveLength;
		this.maxHeight = maxCurveHeight;
		this.denstyKfcnt = denstyKfcnt;
		this.roundKfcnt = roundKfcnt;
		this.ratBasToTechKfcnt = ratBasToTechKfcnt;
		this.graphObjects = {
			

			// СДЕЛАТЬ КАК-ТО ТАК:
			curves: calcCurvesParam(),


			axisAndGrids: undefined,
			relationships: undefined
		};


		// соответственно функцию закрыть и не публиковать
		function calcCurvesParam () {

			var arr = [];

			// пробегаем по все кривым  описанным в JSON
			for(var i= 0; Data.lessons[i]; i++){
				arr.push(new CurveStruct( i, Data.lessons[i]));
			}
			return arr;
		}
		
		...
	}


Опыта мало, а колхоз хочется разводить по-меньше)

Возможно есть ошибка в архитектуре и это делается всё проще, если есть такой вариант, расскажите пожалуйста :)

warren buffet 17.09.2016 20:01

Короче, если что-то вычисляется в условно говоря области деклараций, то там не нужны функции, если эти функции не используются повторно. А если они используются повторно, в том числе как методы, то они уже будут написаны для повторного использования и таких черезодноместо проблем не будет.

На жабе скрипучей можешь рисовать какую угодно архитектуру, ей все почти можно. Просто надо понимать зачем тебе this.property Для интерфейса. Чтобы пользоваться объектом, obj.foo(bar), var foo=obj.baz, и так далее. Если какие-то методы или свойства НЕ нужны в интерфейсе, то и не надо их "выводить" наружу.

В классовом ООП это были бы public и private свойства с методами, а в жабе скрипучей все через жопу, поскольку классов не было, теперь они есть, но все равно уебищные.

warren buffet 17.09.2016 20:10

Цитата:

// без вызова calcCurvesParam(dataInput)

Это значит объекты не нужны. Просто делаешь функцию со всей тряхомудией внутри - функциями и объектами и массивами и переменными - и она выполяется как обычно.

Ну то есть смотри, если у объекта всего 1 метод в интерфейсе - calcCurvesParam - то на кой он зачекинился объектом? Сделай этот метод ролью всей функции и все будет работать по ее вызову.

warren buffet 17.09.2016 20:23

На каждую такую хрень

this.distanceBtwCurves = distCrvs;

посмотри и ответь на вопрос, будет ли она применяться после сотворения мира так

foo.distanceBtwCurves=123;

или так

var bar=foo.distanceBtwCurves;

или нет. Если нет, выпиливай this и посмотришь сколько их останется.


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