Работая снаружи, первая важная концепция здесь - анонимные функции.
var Obj = (function() { /* do work */})();
Проще говоря, мы создаем анонимную функцию, а затем немедленно ее выполняем и назначаем возврат из анонимной функции.в переменную с именем Obj.
Зачем кому-то это нужно?
В этом случае она используется для создания частной области.Локальные переменные в javascript ограничиваются функцией, в которой они определены.Например:
function test() {
var a = 10;
}
// a is not defined here.
В последнем примере a
действительно существует только внутри области действия функции, которая его определила.Javascript немного сложен в этом отношении, потому что, опуская ключевое слово var
, вы можете определить глобальную переменную.
Так что в приведенном вами примере они используют эту анонимную функцию для создания области видимости для некоторыхпеременные, которые будут использоваться, но в конечном итоге захотят их выбросить, как только будет завершено выполнение функции.
Далее:
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
// SNIP
})();
Это создаст новую функцию с именем constructor
.Важно отметить, что функции javascript - это объекты первого класса , что означает, что они работают так же, как и любой другой объект, и могут быть назначены переменной.Эта функция ограничена анонимной функцией.Так что попытка вывести constructor
за пределы своей функции не работает.Например,
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
// SNIP
})();
typeof(constructor) // <= undefined
Пока, если бы вы выполнили отрывки до сих пор, то Obj
был бы не определен.Теперь давайте перейдем немного к концу и посмотрим на возвращение.
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
// SNIP
return constructor;
})();
Поэтому, когда анонимная функция вызывается, она возвращает конструктор.Эта функция, которая передается обратно, назначена на Obj
.Это возвращает конструктор из локальной области функции и присваивает значение переменной.Затем вы сможете вызвать его
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
// SNIP
return constructor;
})();
var o1 = new Obj("t", "v");
o1.type // <= "t"
o1.value // <= "v"
Далее у нас есть интересная строка
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
constructor.prototype = { };
// SNIP
return constructor;
})();
Это устанавливает прототип для конструктора в пустой объект.Объяснение деталей прототипов является частью этой статьи, но упрощение состоит в том, что прототип определяет методы экземпляра, которые доступны для объекта, созданного конструктором.Один «прототип» используется совместно и будет использоваться для определения методов, которые будут доступны для объектов, которые создаются путем вызова new Obj()
.
Далее у нас есть локально определенный массив
var types = [
"Bool", "Int", "Real", "String", "Name", "Null",
"Array", "Dict", "Stream", "Ref",
"Cmd", "Error", "EOF", "None"
];
Помните, что мы внутри функции, эта переменная ограничена областью действия внешней анонимной функции.
Далее мыцикл через этот массив, и настроить некоторые вещи
for (var i = 0; i < types.length; ++i) {
var typeName = types[i];
constructor[typeName] = i;
constructor.prototype["is" + typeName] =
(function (value) {
return this.type == i &&
(typeof value == "undefined" || value == this.value);
});
}
Здесь происходят две интересные вещи.Сначала он устанавливает «статическое» свойство для constructor
, а затем создает новую функцию на прототипе конструктора.Эта функция называется "is" + typeName
.Таким образом, мы должны сгенерировать кучу методов экземпляра с именем вещи типа: "isBool", "isInt", "isReal" и т. Д.
constructor.prototype.lookup = function(key) {
function lookup(key) {
if (!(this.value.contains(key)))
return Obj.nullObj;
return this.value.get(key);
}
}
Далее мы определяем другой метод экземпляра с именем lookup
и выполняемнекоторая работа.
Наконец, мы создаем некоторые статические свойства из нашего конструктора и замораживаем их (чтобы их нельзя было изменить или расширить)
Как только все будет сказано и сделано, Obj
, должен указывать на функцию конструктора, и мы должны иметь возможность говорить что-то вроде:
var myType = new Obj("MyType",undefined);
myType.isBool(undefined) //instance method
Obj.Bool // static property
В любом случае, я надеюсь, что это помогло немного объяснить некоторые из используемых понятий.Большой вывод должен заключаться в том, что function
может использоваться для управления областью видимости, и что функции являются функциями первого класса и могут передаваться как переменные.Вы также можете ссылаться на свойство объекта, используя точечную нотацию (obj.property
) или скобочную нотацию (obj["property"]
).
Существует множество других вещей, которые нужно изучить, и все предложения по книгам безупречныв этой теме.Если это не было упомянуто, я бы также порекомендовал Eloquent JavaSript от Haverbeke .