Почему в JavaScript функция, которую рассматривают и конструктор и объект?

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

См. Парнас, 1972 .

Таким образом, в коде клиента этот стиль предпочтителен:

PaperBag paperBag = paperBagsRepository.get(paperBagId);
PlasticBag plasticBag = plasticBagsRepository.get(plasticBagId);

У вас есть , чтобы сделать это таким образом? Нет. Ни Парнас, ни Полиция DDD не пойдут, чтобы пнуть вашу дверь. Но их разделение облегчает изменение кода , что является важным свойством для устойчивого успеха.

5
задан 16 December 2008 в 18:23
поделиться

8 ответов

Ваше понимание является неправильным:

myFunction().myProperty; // myFunction has no properties

Причина это не работает, состоит в том, потому что ".myProperty" применяется к возвращенному значению "myFunction ()", не к объекту "myFunction". К остроумию:

$ js
js> function a() { this.b=1;return {b: 2};}
js> a().b
2
js> 

Помните, "()" оператор. "myFunction" не является тем же как "myFunction ()". Вам не нужен "возврат" когда instanciang с новым:

js> function a() { this.b=1;}
js> d = new a();
[object Object]
js> d.b;
1
12
ответ дан 18 December 2019 в 05:22
поделиться

Для ответа на конкретный вопрос технически функции всегда являются объектами.

Например, можно всегда делать это:

function foo(){
  return 0;
}
foo.bar = 1;
alert(foo.bar); // shows "1"

Функции JavaScript ведут себя несколько как классы на других языках ООП, когда они используют this указатель. Они можно инстанцировать как объекты с новым ключевым словом:

function Foo(){
  this.bar = 1;
}
var foo = new Foo();
alert(foo.bar); // shows "1"

Теперь это отображение от других языков ООП до JavaScript перестанет работать быстро. Например, нет на самом деле никакой такой вещи как классы в JavaScript - объекты используют опытную цепочку для наследования вместо этого.

если Вы собираетесь сделать какой-либо вид значительного программирования в JavaScript, я настоятельно рекомендую JavaScript: Хорошие Части Crockford, тем парнем Вы послали по электронной почте.

5
ответ дан 18 December 2019 в 05:22
поделиться

"Глобальный" объем JavaScript (по крайней мере, в браузере) window объект.

Это означает это, когда Вы делаете this.myProperty = "foo" и вызовите функцию как плоскость myFunction() Вы на самом деле устанавливаете window.myProperty = "foo"

Вторая точка с myFunction().myProperty это здесь, Вы смотрите на возвращаемое значение myFunction(), настолько естественно, который не будет иметь никаких свойств, поскольку это возвращает пустой указатель.

То, о чем Вы думаете, является этим:

function myFunction()
{
    myFunction.myProperty = "foo";
}

myFunction();
alert(myFunction.myProperty); // Alerts foo as expected

Это - (почти) то же как

var myFunction = new Function('myFunction.myProperty = "foo";');
myFunction();

Когда Вы используете его в new контекст, затем "возвращаемое значение" является Вашим новым объектом, и "этот" указатель изменяется, чтобы быть Вашим новым объектом, таким образом, это работает, как Вы ожидаете.

4
ответ дан 18 December 2019 в 05:22
поделиться

Нет ничего волшебного о функциях и конструкторах. Все объекты в JavaScript являются … хорошо, объектами. Но некоторые объекты являются более особенными, чем другие: а именно, встроенные объекты. Различие заключается главным образом в следующих аспектах:

  1. Общая обработка объектов. Примеры:
    • Числа и Строки неизменны (⇒ константы). Никакие методы не определяются для изменения их внутренне — новые объекты всегда производятся как результат. В то время как у них есть некоторые врожденные методы, Вы не можете изменить их или добавить новые методы. Любые попытки сделать так будут проигнорированы.
    • null и undefined специальные объекты. Любая попытка использовать метод на этих объектах или определить новые методы вызывает исключение.
  2. Применимые операторы. JavaScript не позволяет (ре), определяют операторы, таким образом, мы придерживались с тем, что доступно.
    • Числа имеют специальный путь с арифметическими операторами: +, -, *, /.
    • Строки имеют специальный способ обработать оператор конкатенации: +.
    • Функции имеют специальный способ обработать оператор "вызова": (), и new оператор. У последнего есть врожденное знание о том, как использовать prototype свойство конструктора, создайте объект с надлежащими внутренними ссылками к прототипу и назовите функцию конструктора на нем установкой this правильно.

При изучении стандарта ECMAScript (PDF), Вы будете видеть, что все они, "дополнительная" функциональность определяется как методы и свойства, но многие из них не доступны программистам непосредственно. Некоторые из них будут выставлены в новом пересмотре стандартного ES3.1 (проект с 15 декабря 2008: PDF). Одно свойство (__proto__) уже выставляется в Firefox.

Теперь мы можем ответить на Ваш вопрос непосредственно. Да, функциональный объект имеет свойства, и мы можем добавить/удалить их по желанию:

var fun = function(){/* ... */};
fun.foo = 2;
console.log(fun.foo);  // 2
fun.bar = "Ha!";
console.log(fun.bar);  // Ha!

Действительно не имеет значения, что на самом деле делает функция — это никогда не приходит к игре, потому что мы не называем его! Теперь давайте определим его:

fun = function(){ this.life = 42; };

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

var context = {ford: "perfect"};

// now let's call our function on our context
fun.call(context);

// it didn't create new object, it modified the context:
console.log(context.ford);           // perfect
console.log(context.life);           // 42
console.log(context instanceof fun); // false

Поскольку Вы видите, что это добавило еще одно свойство к уже существующему объекту.

Для использования нашей функции в качестве конструктора, мы должны использовать new оператор:

var baz = new fun();

// new empty object was created, and fun() was executed on it:
console.log(baz.life);           // 42
console.log(baz instanceof fun); // true

Как видете new сделанный нашей функцией конструктор. Следующие действия были сделаны new:

  1. Новый пустой объект ({}) был создан.
  2. Его внутреннее опытное свойство было установлено на fun.prototype. В нашем случае это будет пустой объект ({}) потому что мы не изменили его всегда.
  3. fun() был назван с этим новым объектом как контекст.

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

Забавные мелочи:

  • Поскольку конструктор является просто объектом, мы можем вычислить его:

    var A = function(val){ this.a = val; };
    var B = function(val){ this.b = val; };
    var C = function(flag){ return flag ? A : B; };
    
    // now let's create an object:
    var x = new (C(true))(42);
    
    // what kind of object is that?
    console.log(x instanceof C); // false
    console.log(x instanceof B); // false
    console.log(x instanceof A); // true
    // it is of A
    
    // let's inspect it
    console.log(x.a); // 42
    console.log(x.b); // undefined
    
    // now let's create another object:
    var y = new (C(false))(33);
    
    // what kind of object is that?
    console.log(y instanceof C); // false
    console.log(y instanceof B); // true
    console.log(y instanceof A); // false
    // it is of B
    
    // let's inspect it
    console.log(y.a); // undefined
    console.log(y.b); // 33
    
    // cool, heh?
    
  • Конструктор может возвратить значение, переопределяющее недавно созданный объект:

    var A = function(flag){
      if(flag){
        // let's return something completely different
        return {ford: "perfect"};
      }
      // let's modify the object
      this.life = 42;
    };
    
    // now let's create two objects:
    var x = new A(false);
    var y = new A(true);
    
    // let's inspect x
    console.log(x instanceof A); // true
    console.log(x.ford);         // undefined
    console.log(x.life);         // 42
    
    // let's inspect y
    console.log(y instanceof A); // false
    console.log(y.ford);         // perfect
    console.log(y.life);         // undefined
    

    Как видете x имеет A с прототипом и всеми, в то время как y наш "явный" объект, который мы возвратили от конструктора.

13
ответ дан 18 December 2019 в 05:22
поделиться

Действительно, Функции являются 'гражданами первого класса': они - Объект.

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

Таким образом, Вы могли вызвать каждую функцию Конструктор, даже если она уезжает this один.

Существуют очень хорошие учебные руководства там на конструкторах, прототипы и т.д. Лично, я узнал о много из Объектно-ориентированного программирования в JavaScript. Это показывает эквивалентность функции, которая 'наследовала' ее прототип, но использование this для заполнения свойств нового объекта и функционального объекта, который использует определенный прототип:

function newA() { this.prop1 = "one"; } // constructs a function object called newA
function newA_Too() {} // constructs a function object called newA_Too
newA_Too.prototype.prop1 = "one";

var A1 = new newA();
var A2 = new newA_Too();
// here A1 equals A2.
4
ответ дан 18 December 2019 в 05:22
поделиться

Во-первых, JavaScript не ведет себя тот же путь об объектах, как C++ / Java делает, таким образом, необходимо бросить те виды идей из окна, чтобы смочь понять, как JavaScript работает.

Когда эта строка выполняется:

var myFunctionVar = new myFunction();

затем this в myFunction() относится к этому новому объекту, который Вы создаете - myFunctionVar. Таким образом эта строка кода:

 this.myProperty = "Am I an object!";

по существу имеет результат

 myFunctionVar.myProperty = "Am I an object!";

Это могло бы помочь Вам смотреть на некоторую документацию относительно new оператор. В JS, new оператор по существу позволяет Вам создавать объект из функции - любая простая функция. Нет ничего специального о функции, которую Вы используете с new оператор, который отмечает его как конструктора, как это было бы в C++ или Java. Поскольку в документации говорится:

Создание пользовательского типа объекта требует двух шагов:

  1. Определите тип объекта путем записи функции.
  2. Создайте экземпляр объекта с новым.

Таким образом, что Вы сделали с кодом

function myFunction(){
    this.myProperty = "Am I an object!";
}

должен создать функцию, которая была бы полезна как конструктор. Причина, почему код myFunction.myProperty сбои - то, что нет никакой названной ссылки myFunction.

1
ответ дан 18 December 2019 в 05:22
поделиться

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

0
ответ дан 18 December 2019 в 05:22
поделиться

Только то, когда Вы инстанцируете с новым ключевым словом, совершает функциональный поступок как конструктора.

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

0
ответ дан 18 December 2019 в 05:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: