Подтвердить что ты не робот

В чем разница между вещью var и функцией thing() в JavaScript?

Мне просто интересно узнать о различии между следующим объявлением объектов JavaScript. В частности, разница между вещественным объектом literal и thing1 объектом класса предметов.

Код:

var thing = {
    sanity:0,
    init:function(){
        //code
    },
    send:function(){
        //code
    }
}

function thing(){
    this.sanity = 0;
    this.init = function(){
        //code
    };
    this.send = function(){
        //code
    };
}

thing1 = new thing();
4b9b3361

Ответ 1

Статические объекты/литералы объектов

Статические объекты или литералы объектов не требуют создания экземпляра с оператором new и также ведут себя как одиночные. Рассмотрим следующий пример:

Код:

var staticObject1 = {
 a: 123,
 b: 456
};
var staticObject2 = staticObject1;
console.log(staticObject1, staticObject2);
staticObject2.b = "hats";
console.log(staticObject1, staticObject2);

Вывод:

Object a=123 b=456  Object a=123 b=456
Object a=123 b=hats Object a=123 b=hats

Обратите внимание, что изменение staticObject2.b также повлияло на staticObject1.b. Однако это не всегда может быть желательным эффектом. Многие библиотеки, такие как Dojo, предлагают метод клонирования объектов, который может облегчить эту ситуацию, если вы хотите сделать копию статического объекта, Продолжая предыдущий пример, рассмотрим следующее:

Код:

var staticObject3 = dojo.clone(staticObject1); // See the doc in the link above
staticObject1.a = "pants";
console.log(staticObject1, staticObject2, staticObject3);

Вывод:

Object a=pants b=hats Object a=pants b=hats Object a=123 b=hats

Обратите внимание, что значения элементов staticObject1 и staticObject2 совпадают, тогда как на staticObject3 не влияют изменения этих других объектов.

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

Это полезно при создании библиотек, требующих переносимости или интероперабельности. Это можно увидеть в популярных библиотеках, таких как Dojo, YUI и ExtJs, где все или большинство методов называются dojo.examplMethod(), YUI().exampleMethod() или Ext.exampleMethod() соответственно.

Статические объекты также можно считать слабо аналогичными struct в C/С++.

Конструкторы классов/созданные объекты

Классы в JavaScript основаны на прототипном наследовании, который является гораздо более сложным предметом и может быть прочитан здесь здесь, здесь и здесь.

В отличие от статических объектов этот метод создания объектов дает уникальную возможность для частных объектов и методов объекта scope из-за свойства JavaScript closerer. Рассмотрим следующий пример частных членов класса:

Код:

var SomeObject = function() {
    var privateMember = "I am a private member";
    this.publicMember = "I am a public member";

    this.publicMethod = function() {
        console.log(privateMember, this.publicMember);
    };
};

var o = new SomeObject();
console.log(typeof o.privateMember, typeof o.publicMember);
o.publicMethod();

Вывод:

undefined string
I am a private member I am a public member

Обратите внимание, что typeof o.privateMember является "undefined" и недоступен вне объекта, но находится изнутри.

Частные методы также могут быть сделаны, но не так просты, но все еще просты в реализации. Проблема заключается в том, что значение this внутри частного метода по умолчанию равно window, и один из двух методов должен применяться, чтобы гарантировать, что this относится к объекту, в котором мы работаем, в этом случае экземпляр SomeObject. Рассмотрим следующий пример:

Код:

var SomeObject = function() {
    var privateMember = "I am a private member";
    var privateMethod = function() {
        console.log(this.publicMember);
    };

    this.publicMember = "I am a public member";
    this.publicMethod = function() {
        console.log(privateMember, this.publicMember);
    };
    this.privateMethodWrapper = function() {
        privateMethod.call(this);
    }
};

var o = new SomeObject();
console.log(typeof o.privateMethod, typeof o.publicMethod, typeof o.privateMethodWrapper);
o.privateMethodWrapper();

Вывод:

undefined function function
I am a public member

Обратите внимание, что при выполнении privateMethodWrapper(), privatemethod выполнялся с использованием call и передавался в this для контекста функции. Все в порядке; однако, предпочтительнее (на мой взгляд) следующий метод: он упрощает область вызова и дает идентичные результаты. Предыдущий пример можно изменить на следующее:

Код:

var SomeObject = function() {
    var self          = this;
    var privateMember = "I am a private member";
    var privateMethod = function() {
        console.log(self.publicMember);
    };

    this.publicMember = "I am a public member";
    this.publicMethod = function() {
        console.log(privateMember, this.publicMember);
    };
    this.privateMethodWrapper = function() {
        privateMethod();
    }
};

var o = new SomeObject();
console.log(typeof o.privateMethod, typeof o.publicMethod, typeof o.privateMethodWrapper);
o.privateMethodWrapper();

Вывод:

undefined function function
I am a public member

Этот ответ послужил основой для публикации в блоге где я приведу дополнительные примеры. Надеюсь, что помогает;)

Ответ 2

Случай 2 ссылается на конструкторы класса javascript . Явное различие заключается в том, что переменная еще не является объектом, поэтому вы не можете внутренне ссылаться на thing1.sanity. Вам нужно будет инициализировать класс, создав экземпляр указанного класса до вызова любых внутренних членов:

var myConstructor = function() {
    this.sanity = 0;
}

// wont work
alert(myConstructor.sanity);

// works
var thing1 = new myConstructor();
alert(thing1.sanity);

Вот статья, глубже, чем мой быстрый пример:

Конструкторы классов и литералы объектов

Ответ 3

Отличие состоит в том, что объект thing1 связан с классом thing1 и наследует (не буквально) прототип thing1.

Например, вы можете позже написать

thing.prototype.initAndSend = function() { this.init(); this.send(); };

Затем вы сможете написать thing1.initAndSend() без изменения thing1. Кроме того, thing1.constructor будет равен методу thing, тогда как {}.constructor равен Object.

Кстати, стандартное соглашение состоит в том, чтобы использовать имена классов.

Ответ 4

В первом методе вы объявляете один объект. Со вторым вы объявляете класс, из которого вы можете создать экземпляр (т.е. Создать) много разных копий.

Ответ 5

Функции - это объекты, а также конструкторы (вы можете создавать их с помощью new).

Хэш-таблицы/объекты ({}) не могут быть созданы, поэтому они обычно используются в качестве структур данных. И я не уверен, разумно ли их называть "Объектами".