Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Fluent Interface внешнего .js (https://javascript.ru/forum/misc/51776-fluent-interface-vneshnego-js.html)

Siend 19.11.2014 13:17

Fluent Interface внешнего .js
 
Впервые делаю текущий интерфейс, поэтому очень туплю. Нашел вот такой пример в википедии:

var Car = (function(){
 
	var speed, color, doors, pub;
 
	function setSpeed(new_speed) {
		speed = new_speed;
		return pub;
	}
 
	function setColor(new_color) {
		color = new_color;
		return pub;
	}
 
	function setDoors(new_doors) {
		doors = new_doors;
		return pub;
	}
 
	pub = {
		'setSpeed': setSpeed,
		'setColor': setColor,
		'setDoors': setDoors,
	};
 
	return pub;
 
})
 
// Обычная реализация
myCar2 = Car();
myCar2.setSpeed(100);
myCar2.setColor('blue');
myCar2.setDoors(5);
 
// Текучий интерфейс
myCar = Car();
myCar.setSpeed(100).setColor('blue').setDoors(5);


Идею понимаю, мы возвращаем в конце каждой функции переменную на объект содержащий все поля которые мы соответственно в дальнейшем можем редактировать.

А как будет выглядеть этот же самый пример если он будет внешний файлом?

Может я чего не понимаю, но просто уже пару раз столкнулся с тем что из внешнего файла я перестаю видеть часть функций и т.п.

jsnb 19.11.2014 13:21

Цитата:

Сообщение от Siend (Сообщение 341739)
А как будет выглядеть этот же самый пример если он будет внешний файлом?

Что значит будет внешним файлом? Если ты перенесешь этот код в файл и загрузишь его в теге script, то логика работы кода никак от этого не изменится.

Siend 19.11.2014 13:44

Хм, ок, а такой вопрос, совсем наверное из основ для чайников:
var Car = (function(){
...
})

что означает такая запись?
Var Car = {} - это объект

fucntion Test(){}
Var Car = Test - это функция

даже пусть так:
Var Car = Test(){} тоже функция (наверное, не проверял),
но что означают круглые скобки вне функции (Test(){})?

Насколько я понимаю это должно быть как то с видимостью переменных связано?

Я к чему спрашиваю, у меня есть следующий код:
(напишу абстрактно, так быстрее и понятнее. Создаю свое собственное контекстное меню)

внешний.js

1.Документ готов:
2.Массив с пунктами и подпунктами Меню
3.Вспомогательные переменные (скорость появления и т.п.)
4.Создать несколько элементов div по клику на которые делать функцию Action
5.Вспомогательные функции нужные только для создания div
6.Функция Action
7.Отключаем контекстное меню
8.Добавляем обработчик правого клика мышки

В результате я хочу получить собственную контекстую менюшку, и возможность ее редактировать в стиле:
MyMenu.Size(30).Speed(10).AddMenu("Creat","Main"). AddMenu("Delete","Main") и т.п.

Как мне лучше поступить? Насколько я понимаю по примеру из вики мне нужно поступить так:

...
3.Вспомогательные переменные (скорость появления и т.п.)
var MyMenu=(function(){
функции обработки переменных (добавление изменение и т.п.)
})

4.Создать несколько элементов div по клику на которые делать
...

Или же так:
...
1.Документ готов:
var MyMenu=(function(){
2.Массив с пунктами подпунктами Меню
3.Вспомогательные переменные (скорость появления и т.п.)
функции обработки переменных (добавление изменение и т.п.)
})

4.Создать несколько элементов div по клику на которые делать
...

Т.е. Если я создам свои переменные внутри функции MyMenu я же их не увижу снаружи, а значит придется и все функции создания div и Action засовывать внутрь функции MyMenu, а мне кажется это не правильно.

jsnb 19.11.2014 14:00

Нафига там функция обернута в скобки ты спроси у тех, кто это писал, ибо там эти скобки никакой практической пользы не несут.
Суть чейнинга в том, чтобы из каждого метода возвращать объект у которого можно вызвать следующий метод.
Цитата:

Сообщение от Siend
Т.е. Если я создам свои переменные внутри функции MyMenu я же их не увижу снаружи, а значит придется и все функции создания div и Action засовывать внутрь функции MyMenu, а мне кажется это не правильно.

А зачем тебе переменные и функции снаружи т.е. в глобале?

Siend 19.11.2014 14:09

да по сути не зачем, просто у меня хреново с представление объектно-ориентированной модели того что я сейчас делаю, да и вообще(

Вообщем в качестве теста попробовал вот так:
var myMenu = (function () {

        var pub

        function AddMenu(a,b) {
            for (var i=0;i<menuList.length;i++)
                if (menuList[i][1] == a) {
                    menuList[i].push(b)
                    menuList.push(b)
                }
            return pub
        }
        
        pub = {
            'AddMenu': AddMenu,
        }
    
    })


Но когда я в основном файле пытаюсь обратиться к MyMenu он говорит что знать не знает о такой... Опять что-то с видимостью. Пробовал так
window.BLABLA = myMenu
не помогло, тоже не видит(

jsnb 19.11.2014 14:13

Скрипты выполняются в том порядке, в котором они идут в HTML. Значит ты пытаешься обратится к MyMenu до того как был выполнен скрипт, который это самое MyMenu создает. Ну или действительно что-то с областями видимости у тебя не так. В общем сделай тестовый пример для большей конкретики.

Siend 19.11.2014 14:44

Вот такой вот пример:

<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="style.css">
<script src="jquery.js" type="text/javascript"></script>
<script src="test.js" type="text/javascript"></script>
<title>Menu</title>
</head>
<body id="menu">
    <script>
	testFunction();	
    </script>
</body>
</html>


test.js
$( document ).ready(function() {
	function testFunction(){
	alert("YES")
	}
});


получаю ошибку:
Uncaught ReferenceError: testFunction is not defined

У меня есть мысль что это может быть потому, что код в test.js выполняется после того как вся страничка будет готова, а в основном хтмл файле он выполняется сразу, соответственно и не видит. Но тогда как решить эту проблему?

Siend 19.11.2014 14:47

...
    <script>
	$( document ).ready(function() {testFunction()})	
    </script>
...

Попробовал вот так, получил вот что:
Uncaught ReferenceError: testFunction is not defined test.html:12(anonymous function) test.html:12n jquery.js:2o.fireWith jquery.js:2e.extend.ready jquery.js:2c.addEventListener.C

jsnb 19.11.2014 14:57

Ну так во-первых, у тебя тот код, что в body выполняется раньше чем тот что внутри ready в test.js, а во-вторых, доступа к testFunction у тбя всё равно не будет т.к. оно недоступно из вне. Сделай в test.js код без всякие ready и window.onload. Но вообще тебе явно надо подучить js, потому что насколько я вижу ты слабо представляешь как работают области видимости.

Siend 19.11.2014 14:59

Так в том то и проблема что мне необходимо чтобы в test.js было .ready, да и тогда почему пример с $( document ).ready(function() {testFunction()}) не сработал, он же тоже должен выполниться, после того как все загрузится?

jsnb 19.11.2014 15:06

Цитата:

Сообщение от Siend (Сообщение 341755)
Так в том то и проблема что мне необходимо чтобы в test.js было .ready

Зачем?

Цитата:

Сообщение от Siend (Сообщение 341755)
да и тогда почему пример с $( document ).ready(function() {testFunction()}) не сработал, он же тоже должен выполниться, после того как все загрузится?

Цитата:

Сообщение от jsnb
во-вторых, доступа к testFunction у тбя всё равно не будет т.к. оно недоступно из вне.

Ну сделай window.testFunction = testFunction, если уж так хочешь в глобал закинуть из ready.

jsnb 19.11.2014 15:19

Как я понял тебе надо что-то вроде этого:
(function(){

var menuObj = {
  method1: method1,
  method2: method2,
  method3: method3
}

function method1() {
  //some code
  return menuObj;
}

function method2() {
  //some code
  return menuObj;
}

function method3() {
  //some code
  return menuObj;
}

window.yourMenu = menuObj;

$(document).ready(function() {
  //этот код будет выполнен после загрузки документа
  yourMenu.method1();
  yourMenu.method2();
  yourMenu.method3();

  yourMenu.method1().method2().method3();
});

})();


Ну а еще лучше сделать полноценный конструктор.

Siend 19.11.2014 15:21

Цитата:

Сообщение от jsnb
Сообщение от Siend
Так в том то и проблема что мне необходимо чтобы в test.js было .ready
Цитата:

Зачем?

В тесте то не зачем, но в нормальном скрипте у меня если убрать
$(document ).ready(function() { ... })

вылезает ошибка на строке:
menu.onmousedown = myDown;

А если добавить
$(document ).ready(function() { ... })

то все ок!!!

вот полный код:
var menu = document.getElementById('menu')
    menu.onmousedown = myDown;
    menu.onmouseup = myUp;
    menu.onmousemove = myMove;

    function myDown(e) {
        switch (e.button) {
            case 0:
                break
            case 2:
                switch (showMenu) {
                    case false:             
                        xMenu = xMouse;
                        yMenu = yMouse;
                        showMenu = true;
                        drawMenu()
                        break
                    case true:
                        clearMenu();
                        break
                }
                break
            default:
                alert('Bad request');
                break
        }
    }

Siend 19.11.2014 15:25

ААААААААА, ФАК ФАК ФАК ФАК, Я ЛООХ!
Кароче, да, вы были правы) Ошибка то вылезала потому что я скрипт подключал в head а там еще не существует элемента с id="Menu"
>__________<

Вообщем осталась последняя проблема которую так и не решил)
У меня в menu.js нужно указать функцию которая будет описана в основном коде страничке, т.е. в index.html

P.S.: Уже решил, в принципе все заработало и так, стоило описать функцию перед подгрузкой скрипта.

Спасибо огромное за помощь, побольше вам жирных плюсов в репутацию!)

jsnb 19.11.2014 15:28

Ну так и суй в ready только тот код, который должен непосредственно с DOM работать. В данном случае это вот этот код:
var menu = document.getElementById('menu')
    menu.onmousedown = myDown;
    menu.onmouseup = myUp;
    menu.onmousemove = myMove;

Siend 19.11.2014 15:40

А нет, кстати, что забавно все равно остался косяк который теперь мне тем более не понятен.

<script>
        function MyMenuActions(a) { alert(a)}
    </script>
<script src="menu.js" type="text/javascript"></script>
    <script>
        myMenu
    </script>

Так все ок, на myMenu не ругается, а вот если сделать
myMeny.AddMenu("Main","New") Выдает ошибку, мол знать не знаю таких функций. В js эта функция выглядит так:

window.myMenu = function () {
        
        var pub

        function AddMenu(a,b) {
            for (var i=0;i<menuList.length;i++)
                if (menuList[i][1] == a) {
                    menuList[i].push(b)
                    menuList.push(b)
                }
            return pub
        }
        
        pub = {
            'AddMenu': AddMenu,
        }
        return pub
    }

jsnb 19.11.2014 15:50

Ну так у тебя myMenu - это функция, у нее нет методов. Делай так:
window.myMenu = (function () {
        
        var pub

        function AddMenu(a,b) {
            for (var i=0;i<menuList.length;i++)
                if (menuList[i][1] == a) {
                    menuList[i].push(b)
                    menuList.push(b)
                }
            return pub
        }
        
        pub = {
            'AddMenu': AddMenu,
        }
        return pub
    })();

Siend 19.11.2014 16:08

ДА, вот теперь это решило проблему)
Спасибо огромное за потраченное на меня время!!!)

Erolast 19.11.2014 19:18

Siend, функции принято с маленькой буквы называть. С большой называют классы (в JS - конструкторы).


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