Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Так ли обязательна самовызывающая анонимная функция? (https://javascript.ru/forum/misc/46430-tak-li-obyazatelna-samovyzyvayushhaya-anonimnaya-funkciya.html)

Universe 09.04.2014 16:04

Так ли обязательна самовызывающая анонимная функция?
 
Разбираюсь с основами ООП в js. Довольно часто натыкаюсь на имитацию классов при помощи самовызывающейся анонимной функции, например вот так:
(function (window) {

    window.ballName = "Ball";

    function Ball(size, weight){
        this.size = size;
        this.weight = weight;
        this.init();

    }

    Ball.prototype = Object.create(Circle); //Наследуем свойства от Circle

    Ball.prototype.init = function(){

    }

    window.Ball = Ball;
}(window));

Вот и возникает вопрос, а так ли необходима сама эта анонимная функция? Не проще ли сделать вот так?
var ballName = "Ball";

function Ball(size, weight)
{
    this.size = size;
    this.weight = weight;
    this.init();
}

Ball.prototype = Object.create(Circle); //Наследуем свойства от Circle

Ball.prototype.init = function(){

};


Существует ли принципиальная разница между этими двумя записями? И если да, то какая?

Octane 09.04.2014 16:09

Это никакая не имитация классов, а обычное замыкание, чтобы в глобал не попали ненужные там переменные и функции

(function () {

	var privateVariable = true;

	typeof privateVariable //→ "boolean"

}());

typeof privateVariable //→ "undefined"


можно еще так

new function () {

	var privateVariable = true;

	typeof privateVariable //→ "boolean"

};

typeof privateVariable //→ "undefined"

Universe 09.04.2014 16:17

Т.е. разница будет лишь в том что если я захочу создать "приватную" переменную, которая не должна попасть в глобальную область видимости - я не смогу сделать этого во втором варианте записи?

Octane 09.04.2014 16:19

да

Universe 09.04.2014 16:29

Можно вас попросить почитать комментарии в коде? Я всё правильно понял?
(function (window) { //Window можно и не передавать, но тогда к нему нельзя будет обратится в локальных функциях

    //Здесь можем записывать публичные переменные, window === this в данном случае
    window.foo = 2;
    this.bar = 3;

    //Также можем создавать "статические" переменные, вешая их непосредственно на функцию
    Ball.STATIC_VAR = "staticVar";

    //Здесь можем записывать "приватные" переменные, которые нужны для функционирования данного класса, но не должны попасть в global
    var ballName; // Данная переменная будет доступна только для функций данной области видимости
    var ballSize = 25;
    //После того как функция выполнится - все переменные в этом блоке будут уничтожены
    //----------------------------
    function Ball(size, weight){
        this.size = size;
        this.weight = weight;
        window.ballName2 = "Tree";
        ballName = "Ball2";
        this.init();
    }

    Ball.prototype = Object.create(Circle); //Наследуем свойства от Circle

    Ball.prototype.init = function(){
        console.log(ballName2);
    }

    window.Ball = Ball;
}(window));

Octane 09.04.2014 16:45

Цитата:

Сообщение от Universe
//Window можно и не передавать, но тогда к нему нельзя будет обратится в локальных функция

тут неудачное название параметра функции, window доступен всегда, такая запись позволяет избавиться от имени неймспейса
var namespace = {};
namespace.property = value;

в данном случает namespace = window
var namespace = window;
namespace.property = value;

window.property == value // → true

то есть мы сможем поменять namespace, как захотим, и не придется во всем коде переписывать его название:
(function (namespace) {

	namespace.property = value;	

}(window));

//или

(function (namespace) {

	namespace.property = value;	

}(otherObject));
поменялся только аргумент функции, в теле ничего менять не пришлось


Цитата:

Сообщение от Universe
//После того как функция выполнится - все переменные в этом блоке будут уничтожены

Нет, их замкнут в себе Ball и init, а так как Ball и init будут доступны по ссылке всегда, то замкнутые переменные никуда не денутся из памяти, они просто не доступны глобально, но доступны внутри Ball и init

Universe 10.04.2014 11:47

Цитата:

Нет, их замкнут в себе Ball и init, а так как Ball и init будут доступны по ссылке всегда, то замкнутые переменные никуда не денутся из памяти, они просто не доступны глобально, но доступны внутри Ball и init
А...ну да...логично.

Цитата:

то есть мы сможем поменять namespace, как захотим, и не придется во всем коде переписывать его название
т.е. это впринципе опциональная вещь?

Octane 10.04.2014 14:17

да, замыкание никак не влияет на доступность глобальных переменных, если только внутри не создать локальную с тем же именем


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