LINUX.ORG.RU

Истиный смысл var.

 


1

1

Начал тут разбираться с js, и обнаружил на разных бложеках уйму холливаров по поводу использования var.

Как известно, в js считается плохим тоном не использовать var везде, в том числе и в глобальной области. Только вот почему ее там (в глобальной) надо использовать, похоже мало кто знает, мож скрывают, хз.

То, что переменная объявленная без var не имеет (скрытого) св-тва DontDelete, и (похоже) переменная c var (конкретно в ноде) не копируется в глобальный объект - это ситуацию до конца не проясняет, потому что остается вопрос, если это все не имеет значения для конкретного кода, почему бы не забить.

Я поковырялся с этим вопросом, и вот что выяснил.

Оказывается, в ноде можно подключать модули не только стандартным require, но и простым eval-read. Вот тут, как раз-таки, и проявляется настоящая причина. Если мы «подключим» наш «модуль» внутри ф-ции, то пер-нные из «модуля» без вар сразу бухаются в глобальный скоп.

Допустим, у нас два файла: основной и модуль.

модуль(пусть будет tst):

a=1
var b=2;
основной:
read=function(file){return require("fs").readFileSync(file, "ascii")}

tst=function(){eval(read("./tst")); console.log(a, b)};
tst()// 1 2
console.log(global.a, global.b)// 1 undefined
Вот так усе просто. Выдавливаем по каплям матрицу.:)



Последнее исправление: anonimous (всего исправлений: 1)
Ответ на: комментарий от anonymous

Я че то не понял, это к чему? конечно будет, ты же объявил а как св-во global. Это все равно, что написать global.a=1.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Типа, фонтанирование, с претензией на илитность, от человека, который «чиста па приколу пазырил JS» ? Ну бывает. Вона, набигаторы с похапе еще и не такое лепят. Лично видел, как кто-то smarty на ноду портировал.

Vit ★★★★★
()
Ответ на: комментарий от anonimous

Это к отдельному вопросу о вроде как отсутствии окружений при реквайре. Окружение это прокладка между функцией и глобалом, в этом треде не встречалась (не путай со скопами).

По теме модулей: ты каждый раз при tst() создаешь отдельный объект. Допустим модуль был фабрикой, которая запоминала созданные объекты в к-л локальном массиве. И был метод к-л обновления всех их. Если ты используешь реквайр, ты получаешь всегда одну и ту же фабрику, поэтому обновление всегда будет работать как надо. А если евал, то во внезапных местах у тебя наплодится фабрик и ты уже не сможешь обновить все разом. Если модуль ставил глобалы, то они будут ставиться каждый раз при tst(), что тоже сомнительное действие.

anonymous
()
Ответ на: комментарий от Vit

Я что на личное мнение право не имею? Я специально высказываюсь, чтобы вскрыть ошибки, если они есть. Но Вы пока аргументированно не показали безосновательность моих доводов. Сначала Вы писали, что, эта фишка для совместной разработки, типа, нужна, а когда я показал, что это слабый аргумент, Вы тут же перепрыгнули на eval, что это мол зло. А почему это зло, толком тоже небось обосновать не сможете, я знаю, что все жужжат о какой то фантомной опасности, но на деле, все это жужжание сводится обычно, к оптимизации кода. Понятно, что кривой код с эвал компилятор не оптимизирует, только вот ведь незадача, единожды вызванный, он погоды не сделает, вот ведь нестыковочка.

anonimous
() автор топика
Ответ на: комментарий от anonymous

Окружение это прокладка между функцией и глобалом, в этом треде не встречалась (не путай со скопами).

В js, окружение и скоп - это, фактически, одно и то же. В твоем примере, разница в том, что с var ты определяешь переменную в неявном глобальном скопе, а без вар - ты просто добавляешь свойство в объект global. Однако в JS есть такая фича, что свойства глобального объекта видны изнутри всех замыканий. В браузерах, это вообще почти одно и тоже (при создании переменных они автоматом копируются в объект window), концептуально(отличия - см 3 абзац начала темы).

ты каждый раз при tst() создаешь отдельный объект.

Насколько позволяет мне судить мое нубское понимание - нет. Конкретно в моем примере, tst - это уже скомпилированный функциональный обект. Каждый раз при вызове он просто ищет переменные в своем собственном окружении. Он не создает заново объекты.

anonimous
() автор топика
Ответ на: комментарий от anonymous

И я, в принципе, мож, толком пока не разобрался в твоих постах, почитаю еще, но в целом, я так понимаю, ты наезжаешь на eval и на интерпретацию, и считаешь, что require каждый раз вызывает eval, что ведет к перекомпиляции, так я понял?

Если так, то я просто выскажу свое предположение по этому поводу, реальных реализаций этих вещей я. конечно не знаю, но думаю следующее.

Начнем с моего изначального поста, где я говорб о подключении с помощью eval. Конечно, если мы будем использовать такое подключение внутри функции, она будет каждый раз эвалить и это не гуд. С другой стороны, ты не хочешь, чтобы модуля были в глобальной области, как объекты (хотя это не проблема, не так уж и много там имен, имя переменной куда записан модуль является объектом, где находятся внутренние имена модуля, так что инкапсуляция уже есть какая-никакая). Здесь есть простой выход - создать отдельный объект, куда скинуть все имена подключенных модулей, а изнутри ф-ций вызывать уже скомпилированные объекты. Я думаю, что require, в принципе, так и сделана, вряд ли там эвалится каждый раз изнутри функции, но, соб-нно, и без require, с одним eval/read можно все грамотно оформить, ИМХО.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Дык пишите как хотите, я вам сразу сказал :)

Vit ★★★★★
()
Ответ на: комментарий от anonymous

А теперь запусти свой код чуть выше и проверь есть ли a в глобалах.

А, только сейчас доперло, что ты хочешь тут сказать. Просто ты сказал «чуть выше», а чуть выше другой код, ты, наверно имел в виду код с эвалом, который вначале.

Тот что в начале код, там а копируется в глобал, оно сразу копируется, при вызове ф-ци, так и было задумано изначально, для демонстрации того, что:

Если мы «подключим» наш «модуль» внутри ф-ции, то пер-нные из «модуля» без вар сразу бухаются в глобальный скоп.

Я писал не про стандартное подключение модулей, а про наколеночную реализацию, для того, чтобы продемонстрировать, где объявление переменной с вар и без вар действительно имеет значение. Т.е. не во всех случаях имеет смысл писать var. Это так, импровизация была.

anonimous
() автор топика
Ответ на: комментарий от anonimous

PS Как возможно обеспечить оптимизацию, чтобы каждый раз не эвалить, при подключении через eval я написал тут: Истиный смысл var. (комментарий), но это непосредственно к теме var отношения не имеет.

anonimous
() автор топика
Ответ на: комментарий от Vit

Ну так тем не менее это не стандарт. Вон даже в статье что ты привёл: «CommonJS is not affiliated with the Ecma International group TC39 working on ECMAScript». В ES6 вроде есть модули, но до него ещё далеко.

Kalashnikov ★★★
()
Ответ на: комментарий от Kalashnikov

А о чем там речь идет? Сейчас, когда подключаются скрипты через Html-страницу - это че не модули штоле? Это модули по сути, нахрена там че то еще стандартизировать? Еще один костыль прибить? Ненужно ящетаю.

anonimous
() автор топика
Ответ на: комментарий от Kalashnikov

Договорились:)

Ну а все таки, какой профит то?

anonimous
() автор топика
Ответ на: комментарий от Kalashnikov

Это одна из общих договоренностей между разработчиками. Которую поддерживают все серверные JS движки. Так же как AMD и т.п. для браузеров. Если кто-то станет лепить свой гениальный лисапед, к нему просто отнесутся как к идиоту.

На эту тему имеется куча наработок. Например, с помощью нехитрой магии я могу из commonjs-овских модулей автоматически генерить код для браузеров. И там не будет ничего лишнего.

Рассматривать голый язык без экосистемы и базовых API просто нет смысла.

Vit ★★★★★
()
Ответ на: комментарий от arturpub

Уж если чему и удивляться, то этому. http://stackoverflow.com/questions/9781285/specify-scope-for-eval-in-javascript

Я че то долго врубался, что вы хотите сказать, но так и не понял. Тот чувак, который там хочет странного, как раз и ноет по-тому поводу, что eval не позволяет ему переопределить переменную в каком то мифическом скопе.

Это тем более странно, что то чего он хочет, и так есть в нативной объектной системе JS:


ob={}
ob.a=1
ob.a=ob.a+1

console.log(ob.a)// --> 2

Не ищет ли он вчерашний день, случаем? Или к чему это?

Да и ответчики тоже какую то пургу метут.

anonimous
() автор топика
Ответ на: комментарий от Vit

Рассматривать голый язык без экосистемы и базовых API просто нет смысла

Ага, а голую экосистему, без языка, это как? На сегодняшний день это обычное дело, мля. Я когда начал учиться быдлокодить, я начал с питона. Я запарился, там, с этим питоник веем, Никаких мля велосипедов, непитоник. Тока наш бох - джанго и иже с ним, либы, х-ибы. Попробуй тока, спроси, как жа код пейсать, тут же порвут на части - непитоник. Подключай сразу foo.py, bar.py, и будет тебе счастье. С таким подходом, скоро всех секретуток и дворников в программисты завербуют, Им индусов мало, видать.

anonimous
() автор топика
Ответ на: комментарий от Vit

Мне они нахрен ни сдались, на их оценки смотреть, мое дело в программирование въехать, а JS, гораздо более свободный язык, куча годных статей о велосипедах и о семантике, и в комьюнити есть специалисты, которые мыслят в категориях семантики языка, а не шаблонами и сахаром. Так что JS, для обучения программированию, годный пока язык, к тому же по нему есть одна неплохая книжка - SICP.

anonimous
() автор топика
Ответ на: комментарий от Vit

И, кстати, про SICP. В MIT, видать, придурки сидят, заставляют бедных студентов велосипедить: писать с нуля объектные системы, интерпреторы, модулировать реальные машины изучать различные парадигмы и подходы к решению инженерных задач. Нет бы сразу, как в Мухосранске, сажали их за Ынтерпрайз, рассказали бы как подключить либу я_за_тебя_все_сделаю_и_обо_всем_позабочусь_спи_мой_малыш.js, недоумки.

anonimous
() автор топика
Ответ на: комментарий от Vit

s/интерпреторы/интерпретаторы/

И посоветуйте мне бесплатный хостинг для ноды с ftp в соседнем теде или здесь. Вы ведь должны знать, раз с нодой работаете? Или жалко?:)

anonimous
() автор топика
Ответ на: комментарий от anonimous

окружение и скоп - это, фактически, одно и то же

Тебе бы книжку какую почитать для установления терминологии. Иначе дальше смысла нет обсуждать, мы на разных языках говорим, и ты путаешь скопы и окружения (которых в js похоже нет).

tst - это уже скомпилированный функциональный обект. Каждый раз при вызове он просто ищет переменные в своем собственном окружении. Он не создает заново объекты.

И какой же код в этом «функциональном объекте»? Попробуй написать функцию, которая семантически не будет отличаться от tst. Код сюда.

Допустим в tst.js было:

var object_cache = [ ];
create = function () {
    var object = { };
    object_cache[object_cache.count+1] = object; // не знаю как правильно брать длину в js
    return object;
}
count = function () {
    return object_cache.count;
}

arturpub ★★
()
Ответ на: комментарий от arturpub

ты путаешь скопы и окружения

Я ничего не путаю. В Ecma-script стандарте даже определен специальный термин [[scope]], он неявный, недоступен программисту для непосредственной модификации, он может быть модифицирован лишь изнутри замыкания с помощью присваивания. Так вот этот scope, является технической (на уровне языка) реализацией окружения. Каждое замыкание создает свое окружение и при вызове функция именно там, в скопе своего замыкания ищет имена. Что ты имеешь в виду под окружением, я не знаю. В JS - так.

И какой же код в этом «функциональном объекте»?

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

anonimous
() автор топика
Ответ на: комментарий от arturpub

Я никак ни пойму, что ты вообще хочешь услышать? Что тебе показать? Что в JS существуют локальные окружения штоле, или что? Если это, то взгдяни на код счетчика, который я приводил выше.

Истиный смысл var. (комментарий)

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

anonimous
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.