Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Как объявить глобальную переменную из функии? (https://javascript.ru/forum/events/37199-kak-obyavit-globalnuyu-peremennuyu-iz-funkii.html)

Владлен 11.04.2013 10:42

Как объявить глобальную переменную из функии?
 
Как объявить глобальную переменную из функии?
Например:
var playerUrl
function playRTrack(playerId, myArray) {
		var rIndex = Math.floor(Math.random()*(arr.length));
		var rElement = arr[rIndex];
		var myPlayer = document.getElementById('player');
		var playerUrl = myUrl + rElement;
		var myDownload = document.getElementById('myDownload');
		myDownload.setAttribute("href", playerUrl);
		myPlayer.setAttribute("src", playerUrl);
		myPlayer.play();
	}

Чтобы значение переменной playerUrl стало глобальным...:help:

devote 11.04.2013 10:47

window.playerUrl = 1

rgl 11.04.2013 11:12

Универсальный способ, работает не только в браузерах, но и там, где windows нет. Не совместим с "use strict" :-(
function f() {
  (function(){return this;})().playerUrl = 1;
}
f();

alert( typeof playerUrl + ": " + playerUrl );


А можно просто присвоить значение не объявляя (т.е. без слова var)

devote 11.04.2013 11:16

Цитата:

Сообщение от rgl
Универсальный способ,

во задвинул... уж поверь если человек не знает как в браузере сделать глобальной, то уж явно не полезет туда где нет объекта window

и что бы не лепить то что ты слепил, можно сделать гораздо проще. И безо всяких функций:
var global = window || this;

global.ololo = 1;

alert(ololo);
"use strict"
var global = window || this;

global.ololo = 1;

alert(ololo);

rgl 11.04.2013 11:22

Кста, таким способом можно доступиться внутри функции до глобальной переменной даже если в функции объявлена одноименная локальная:
var test = "global test";
function f() {
  var test = "local test";
  alert( test );
  alert( (function(){return this;})().test );
  (function(){return this;})().test = "new value"
}
f();

alert( test );

rgl 11.04.2013 11:25

Цитата:

Сообщение от devote (Сообщение 245486)
и что бы не лепить то что ты слепил, можно сделать гораздо проще. И безо всяких функций:

Нельзя внутри функции-метода, внутри функции-конструктора, внутри функции, вызванной call или apply.

devote 11.04.2013 11:26

Цитата:

Сообщение от rgl
Кста, таким...

var global = window || this;

var test = "global test";
function f() {
  var test = "local test";
  alert( test );
  alert( global.test );
  global.test = "new value"
}
f();
 
alert( test );

devote 11.04.2013 11:27

Цитата:

Сообщение от rgl
Нельзя внутри функции-метода.

а кто говорит о том что нужно это совать внутрь функции?
я обычно пишу так:
(function(window) {
    ...
})(window || this);

rgl 11.04.2013 11:37

Цитата:

Сообщение от devote (Сообщение 245493)
var global = window || this;

var test = "global test";
function f() {
  var test = "local test";
  alert( test );
  alert( global.test );
  global.test = "new value"
}
f();
 
alert( test );

:nono: :nono: :nono:
var global = window || this; - абсолютно бессмысленная конструкция, т.к. там где window есть, не нужна, а там где нет - падает. Так что:
var global = (function(){return this;})(); // :yes:

devote 11.04.2013 11:39

Цитата:

Сообщение от rgl
а там где нет - падает.

var global = (function(){return this || window})();

devote 11.04.2013 11:42

при включении строгого режима:
"use strict";
var global = (function(){return this || window})();

alert(global);

rgl 11.04.2013 11:42

Цитата:

Сообщение от devote (Сообщение 245499)
var global = window || (function(){return this})();

Падает, падает. До this (или во втором примере до (function(){return this})(); ) дело в любом случае не доходит.

devote 11.04.2013 11:44

Цитата:

Сообщение от rgl
Падает, падает

я в курсе, из за отсутствия объявленной переменной. Я исправил выше

rgl 11.04.2013 11:49

Цитата:

Сообщение от devote (Сообщение 245500)
при включении строгого режима:
"use strict";
var global = (function(){return this || window})();

alert(global);

А это работает, т.к. до windows дело не доходит, а то бы упало.

devote 11.04.2013 11:50

Цитата:

Сообщение от rgl
А это работает, т.к. до windows дело не доходит, а то бы упало.

в этом случае доходит до window так как включен строгий режим, и this внутри функции равен значению null. Поэтому берется значение из переменной window

rgl 11.04.2013 12:22

devote,
Если windows есть, то да, все нормально, а если нет - ПАДАЕТ.
Разговор вообще какой-то беспредметный, трудно придумать случай, когда пишущий скрипт не знает, для браузера от пишет или нет, т.е. есть window или нет. Нет, можно конечно писать какие-то универсальные функции, которые потом используются и там и сям, но в этом случае в глобальные переменные лазить не надо. Никогда не надо, но в этом случае - особенно.
Кста, для экспериментов без браузера использую
1. Windows Script Host - движок тот же, что у шестого IE, даже под windows 7, в которую входит 9-й IE, в Windows Script Host движок от шестого.
2. V8 - движок от гугла, тот же, что и в хроме. Можно скачать исходники и собрать.
Также можно скачать и собрать движок от мозилы Spider Monkey, но я им не пользовался.

devote 11.04.2013 12:27

Цитата:

Сообщение от rgl
Если windows есть, то да, все нормально, а если нет - ПАДАЕТ.

то есть и this нет и window нет? хм.. и где такое бывает? хотя даже если и бывает, то решить не сложно:
var global = (function(self){return this || typeof window !== 'undefined' && window || self})(this);
Тут у нас получилось простое решение, если нет объекта this (то есть оно равно null) попытаемся получить window, и если и оно не определено, то тогда просто возвращаем ссылку на текущий контекст.

devote 11.04.2013 12:36

В Node.JS глобальный объект имеет имя global, вот решение с учетом этого:
var global = (function(self){
    return typeof global !== 'undefined' && global || this || typeof window !== 'undefined' && window || self;
})(this);

rgl 11.04.2013 12:37

Цитата:

Сообщение от devote (Сообщение 245531)
то есть и this нет и window нет? хм.. и где такое бывает?

this нет (точнее, null) при "use strict", window нет при программировании не для браузера. Следовательно, и то и другое при сочетании обоих условий. Хотя действительно для сочетания условий надо сделать что-то нетривиальное (напр, скачать и собрать V8), т.к. в браузере есть windows, а под Windows Script Host, как я уже сказал, движок от шестого IE, который не понимает "use strict"

with-love-from-siberia 11.04.2013 15:29

Цитата:

Сообщение от rgl
Windows Script Host - движок тот же, что у шестого IE

Но даже здесь есть проблема. Это редкий случай, но если кому-то понадобиться объявить функцию таким способом - это у него не получится. Проверялось на Vista и XP, WSH 5.7.

Простой вызов cscript z.js не вызывает проблем.
z.js
(function(that)
{
	that.a = function()
	{
		WScript.Echo(1);
	};
})(this);

a();


Этот вызов cscript z.wsf приведет к краху скрипта.
z.wsf
<?xml version="1.0" encoding="utf-8" ?>
<package>
<job id="crash">
<script language="javascript" src="z.js"></script>
</job>
</package>


Пока это единственное решение проблемы:
// вариант 1
a.call();
a.apply();

// вариант 2
b = a;
b();


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

rgl 11.04.2013 18:30

with-love-from-siberia,
Падает совсем не потому, а из-за использования WScript.Echo там где не надо. Вот так все нормально, хоть запускай через js, хоть через wsf
(function(that)
{
	that.a = 1;
})(this);

WScript.Echo( a );

rgl 11.04.2013 18:36

WScript - не JavaScript'овый объект, а WScript.Echo - не функция. Попробуйте, напр.
WScript.Echo( typeof WScript.Echo );
а
WScript.Echo( typeof WScript );
или
WScript.Echo( WScript.Echo instanceof Function );
вообще падают, чего (с точки зрения JavaScript) происходить не должно.

rgl 11.04.2013 19:02

Цитата:

Сообщение от rgl
var global = (function(){return this;})();

Кста, никто не мешает использовать и в стрикт моде:
var global=(function(){return this;})();
"use strict";
// и дальше все стрикт

Владлен 11.04.2013 19:38

Блин, что ж такое.
function test() {
window.a = 1
alert(a)
}
alert(a)

внутри функции выводит а снаружи нет.(

with-love-from-siberia 11.04.2013 20:36

Цитата:

Сообщение от rgl
WScript - не JavaScript'овый объект, а WScript.Echo - не функция. Попробуйте, напр.

Я в курсе. Но дело не в этом. WScript.Echo всего лишь для иллюстрации. Попробуйте без нее. Например, так:
(function(that)
{
	that.a = function()
	{
	};
})(this);

a();


Понятно, что это искусственный пример, но он иллюстрирует проблему.

rgl 12.04.2013 12:13

with-love-from-siberia,
Ваша правда. Кста, так работает:
(function(that)
{
	that.a = function()
	{
		WScript.Echo( "It works!" );
	};
})(this);

a.call();

skillful 05.08.2016 19:38

Здравствуйте. Понимаю - тема устарела, но все же. У меня похожий код. Нужно переменную socket сделать глобальной. Прошу помощи...
"use strict";

(function()
{
	// ======== global vars from config ========   
	var srvaddress = url_base + 'include/socket/';//url каталога
	var startserveraddress = srvaddress+'wsstart.php';
	var chataddr = 'ws://localhost:8889';


	// ======== private vars ========
	var socket;
	var xhttp;

	////////////////////////////////////////////////////////////////////////////
	var init = function()
	{
		//https://learn.javascript.ru/websockets Docs
		socket = new WebSocket(chataddr + '/' + cookies + '/516616546465464');

		socket.onopen = connectionOpen; //Соединение установлено
		socket.onmessage = messageReceived; //Получены данные
		//socket.onerror = errorOccurred; 
		//socket.onopen = connectionClosed;

		document.getElementById("msg-send").onclick = function()
		{
			//sendMessage();
			messagesend();
		};

	};

	function messagesend()
	{
	}

	function connectionOpen()
	{
		socket.send("{\"act\":\"start\", \"msg\":\"Connection with "+chataddr+". Подключение установлено обоюдно, отлично!\"}");
	}

	function messageReceived(e)
	{
		var json = eval("(" + e.data + ")");

	}

	function connectionClose() {
		socket.close();
	}

	return{
		// ---- onload event ----
		load : function () {
			window.addEventListener('load', function () {
				init();
			}, false);
		}
	}
})().load();

warren buffet 05.08.2016 21:19

Ну так сотри var перед ней и она вылезет за пределы функции. Если там еще есть функция снаружи, то напиши явно window.socket= и далее по тексту. Ты же читал тему сначала или забил?


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