Как вы называете этот синтаксис JavaScript, чтобы я мог исследовать его?

1) В следующем коде, какова причина создания переменной gameOfLive, а не только function gameOfLife()?

2) Что такое gol? Это похоже на массив, но я не знаком с синтаксисом или тем, как он называется.

Я изучаю http://sixfoottallrabbit.co.uk/gameoflife/

if (!window.gameOfLife) var gameOfLife = function() {

    var gol = {
        body: null,
        canvas: null,
        context: null,
        grids: [],
        mouseDown: false,
        interval: null,
        control: null,
        moving: -1,
        clickToGive: -1,
        table: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(''),
        tableBack: null,

        init: function(width, height) {
            gol.body = document.getElementsByTagName('body')[0];
            gol.canvas = document.createElement('canvas');
            if (gol.canvas.getContext) {
                gol.context = gol.canvas.getContext('2d');
                document.getElementById('content').appendChild(gol.canvas);
                gol.canvas.width = width;
                gol.canvas.height = height;
                gol.canvas.style.marginLeft = "8px";

                gol.control = document.getElementById('gridcontrol');

                gol.canvas.onmousedown = gol.onMouseDown;
                gol.canvas.onmousemove = gol.onMouseMove;
                gol.canvas.onmouseup = gol.onMouseUp;

                gol.addGrid(48,32,100,44,8);

                gol.refreshAll();
                gol.refreshGridSelect(-1);
                gol.getOptions(-1);

                gol.genTableBack();
            } else {
                alert("Canvas not supported by your browser. Why don't you try Firefox or Chrome? For now, you can have a hug. *hug*");
            }
        },
    }
}

person jason    schedule 08.07.2010    source источник
comment
Привет. Я автор JS, который вы изучаете. Во-первых, я хотел бы извиниться. Это ОГРОМНЫЙ беспорядок. Без комментариев, тонны наспех зарубленного кода. Однако я работаю над гораздо более аккуратной версией. Многие люди ответили на ваш вопрос о коде, и я надеюсь, что они помогли. Я обязательно сообщу вам о более аккуратной версии, когда закончу. Но наслаждайтесь изучением беспорядка, который я создал. хD   -  person Joseph Mansfield    schedule 09.07.2010
comment
Я наслаждался этим полностью! :-) Пожалуйста, дайте мне знать, когда выйдет более аккуратная версия. Я смог изменить «правила», чтобы учесть цвет, и заполнить на основе правил, включая их. Довольно весело!   -  person jason    schedule 10.07.2010


Ответы (7)


var gameOfLife = function() { }

является выражением функции, тогда как

function gameOfLife() { }

является объявлением функции.

Процитируем Юрия ‘kangax’ Зайцева о выражениях функций и объявлениях функций:

Есть тонкая разница в поведении объявлений и выражений.

Прежде всего, объявления функций анализируются и оцениваются до того, как будут обработаны любые другие выражения. Даже если объявление расположено последним в источнике, оно будет оцениваться прежде любых других выражений, содержащихся в области видимости. […]

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

В этом случае, как упоминает Джоэл Кохорн в комментарии, gameOfLife определяется условно, поэтому необходимо использовать функциональное выражение.

Общим вариантом использования этих условно определенных функций является расширение возможностей JavaScript в браузерах, которые не имеют встроенной поддержки новых функций (недоступно в предыдущих версиях ECMAScript/JavaScript). Вы не хотите делать это с помощью объявлений функций, так как они все равно перезапишут собственные функции, что, скорее всего, не то, что вам нужно (учитывая скорость и т. д.). Краткий пример этого:

if (!Array.prototype.indexOf) { 
    Array.prototype.indexOf = function(item, from) {
        /* implement Array.indexOf functionality,
           but only if there's no native support */
    }
}

Одним из основных недостатков функциональных выражений является то, что вы фактически присваиваете переменной анонимную функцию. Это может затруднить отладку, так как имя функции обычно неизвестно, когда выполнение скрипта останавливается (например, в установленной вами точке останова). Некоторые отладчики JavaScript, такие как Firebug, пытаются дать имя переменной, которой была назначена функция, но, поскольку отладчику приходится угадывать это, анализируя содержимое скрипта на лету, это может быть слишком сложно (что приводит к (?)() вместо имени функции) или даже быть неверным.

(для примера читайте дальше на странице, правда ее содержание не совсем подходит для новичков)

person Marcel Korpel    schedule 09.07.2010
comment
+1. В этом случае функция объявлена ​​условно (if (!window.gameOfLife)), поэтому им нужно отдать предпочтение выражению. - person Joel Coehoorn; 09.07.2010
comment
В чем смысл этого условного объявления? Я не вижу никаких преимуществ в добавлении этого оператора if. Если вы просто используете обычное объявление функции, разве оно не будет объявлено только один раз? - person Lèse majesté; 09.07.2010
comment
@Lèse: Если вы хотите предоставить некоторые функции, недоступные в каждом (версии каждого) браузера, вы можете использовать что-то вроде if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, from) { … };, см. code.google.com/p/oz-js/source/browse/trunk/oz.js#234. Используя объявление функции, вы всегда будете перезаписывать нативную функцию, что предпочтительнее в большинстве случаев. - person Marcel Korpel; 09.07.2010
comment
Да, такое использование имеет смысл. Но в этом случае, разве это не просто проверка того, было ли объявлено gameOfLife()? Я посмотрел файл .js, и непонятно, как gameOfLife() могло быть уже объявлено уже при запуске скрипта. - person Lèse majesté; 09.07.2010
comment
@Lèse: Я думаю, это скорее общая проверка вменяемости. Я слишком устал, чтобы сейчас разбираться в этом конкретном случае, но я могу представить случаи, когда скрипты могут быть каким-то образом вставлены несколько раз; вы не хотите потерять свои значения, перезаписав их первоначальными. - person Marcel Korpel; 09.07.2010

  1. В JavaScript функции являются объектами первого класса. Вы можете хранить их в объектах (переменных) и передавать их в качестве аргументов функциям. Каждая функция на самом деле является Function объектом.

  2. gol — это объект, который инициализируется с использованием нотации объектного литерала .

person Daniel Vassallo    schedule 08.07.2010
comment
Основная причина использования синтаксиса переменных состоит в том, чтобы напомнить себе (или другим программистам), что gameOfLife на самом деле является переменной. Его можно изменить и перезаписать, как и любой другой. Просто в настоящее время он выполняет функцию. Синтаксис var gameOfLife = function... служит визуальным напоминанием. - person Ryan Kinal; 09.07.2010
comment
@Ryan: это не отвечает на вопрос, почему вместо объявления функции используется выражение функции. Другая причина использования var заключается в том, чтобы определить gol локально для области действия gameOfLife. - person Marcel Korpel; 09.07.2010
comment
Как автор кода, я хотел бы добавить некоторую информацию: я объявляю gameOfLife по сути как пространство имен для хранения всего остального, из чего состоит мое приложение. Если вы прокрутите его до конца, вы увидите, что функция gameOfLife() заканчивается на return gol; а затем после финального } есть (). Поэтому я выполняю функцию и сохраняю возвращаемое значение в gameOfLife. И что возвращает? Он возвращает объект gol. Таким образом, gameOfLife становится синонимом гола. gameOfLife — красивое имя, используемое за пределами пространства имен, а gol — короткое имя, используемое внутри. - person Joseph Mansfield; 09.07.2010


1) В следующем коде, какова причина того, что gameOfLive является переменной, а не просто «функцией gameOfLife()»?


Переменные, определенные на глобальном уровне, являются членами объекта окна. Таким образом, сделав его переменной, вы можете использовать синтаксис window.gameOfLife(). Именно поэтому они могут использовать проверку if (!window.gameOfLife) в начале вашего фрагмента.

Но это на самом деле не объясняет, почему они решили сделать это таким образом, и объявление функции сделало бы то же самое. Ответ Марселя Корпеля лучше объясняет "почему" из двух вариантов.


2) что такое гол? Это похоже на массив, но я не знаком с синтаксисом или тем, как он называется.


Синтаксис называется компактной записью объекта. Здесь интересно то, что «компактный» объект объявляется внутри функции. Объявление объекта внутри такой функции полезно, потому что вы можете использовать его для создания объектов javascript с (фактически) закрытыми членами.

Главное помнить, что функции и объекты в javascript одно и то же. Таким образом, полная функция gameOfLife() на самом деле является определением объекта. Кроме того, объект gol, объявленный как член gameOfLife, скорее всего, является частью общего метода определения закрытых членов. Функция/объект gameOfLife() вернет этот объект gol. Все остальные элементы, объявленные внутри функции/объекта gameOfLife(), фактически становятся закрытыми членами возвращаемого экземпляра gol, в то время как все, что объявлено внутри самого объекта gol, является общедоступным. Что они действительно хотят сделать, так это в конечном итоге написать такой код:

var game = new gameOfLife();

Теперь, когда они это сделают, игровая переменная будет содержать объект gol. Методы в этом объекте по-прежнему имеют доступ к элементам, объявленным в полной функции gameOfLife(), но другой код не имеет доступа (по крайней мере, не так легко). Таким образом, эти элементы фактически являются частными. Элементы в самом объекте gol по-прежнему общедоступны. Таким образом, у вас есть объект как с закрытыми, так и с открытыми членами для надлежащей инкапсуляции/скрытия информации, точно так же, как вы строите с другими объектно-ориентированными языками.


person Joel Coehoorn    schedule 08.07.2010
comment
@Marcel - см. предпоследнее предложение первой части моего ответа. - person Joel Coehoorn; 09.07.2010
comment
да, извините, вы правы, вы также сказали, что «объявление функции сделает то же самое». Я сейчас посплю... ;-) - person Marcel Korpel; 09.07.2010
comment
@ Марсель, честно говоря, это предложение было отредактировано после того, как я прочитал ваш ответ, снова посмотрел на исходный вопрос, и мне пришлось ударить меня по голове, потому что я ответил не на то. Я почему-то подумал, что он спрашивает о том, как этот объект можно использовать в качестве члена объекта окна. - person Joel Coehoorn; 09.07.2010

Помещение функции в переменную позволяет вам прийти позже и заменить ее другой функцией, заменив функцию прозрачно для остального кода. Это то же самое, что вы делаете, когда указываете "onClick=" в виджете формы.

person Curtis    schedule 08.07.2010

конечно: объяснить синтаксис:

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

gameOfLife()

gol — это объект (хэш), а «init» — еще один пример вышеприведенного синтаксиса, за исключением того, что он помещается непосредственно в ключ «init» в хеше «gol». поэтому эта функция, в свою очередь, может быть вызвана:

gol["init"](w,h)
person eruciform    schedule 08.07.2010

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

person TNi    schedule 08.07.2010
comment
Не совсем верно: массив — это своего рода объект, но вы не можете определить массив с помощью фигурных скобок, как вы подразумеваете. Существуют серьезные различия между выражениями функций (как в примере) и объявлениями функций (как того хотел OP): «объявления функций анализируются и оцениваются до того, как будут обработаны любые другие выражения. […] Еще одна важная черта объявлений функций заключается в том, что их условное объявление не стандартизировано и различается в разных средах. Вы никогда не должны полагаться на условное объявление функций и вместо этого использовать функциональные выражения». - person Marcel Korpel; 09.07.2010
comment
Я никогда не говорил, что массивы могут быть определены с помощью фигурных скобок, только то, что я нашел полезным провести сравнение между объектами JavaScript и ассоциативными массивами. Спасибо за ссылку. Я предположил, что между определениями двух функций есть некоторые различия, хотя не смог найти источник. Практически говоря, по моему опыту, легко понять, когда что использовать, и часто это не имеет большого значения. - person TNi; 09.07.2010