2009-10-05 2 views
1

Пожалуйста, см следующий сценарий:JavaScript функция инкапсуляция вне объекта

var x = function(param){ 
    this.data=param; 

    this.y = function(){ 
     alert(this.data) 
    } 

    return this; 
} 

/* 
    x.prototype.z = function(){ 
     alert(this.data); 
    } 
*/ 

x(123).y(); 
x(123).z(); // This should behave same as y() 

Когда я называю х (123) .y() затем отображается сообщение . Функция у() объявленная внутри х()

Теперь я хочу объявить еще одну функцию г(), которая будет находиться за пределами х() но будет вести себя такие же как y() [ассоциировать с x()]

Возможно ли это? Если возможно, как?

ответ

3

Вам не хватает new при звонке x(). В противном случае внутри тела функции будет ссылаться на глобальный объект (window в контексте браузера), а не на экземпляр x.

Именно поэтому вызов z() (после того, как он не комментирует код) не работает. Вызов y() работает только по совпадению при создании глобальной переменной data, значение которой будет перезаписано следующим вызовом x().


Я понятия не имею, что вы пытаетесь достичь, и от того, что я могу видеть, это, скорее всего, не является хорошей идеей.Во всяком случае, вот пример того, как избавиться от явных new при создании объектов:

var x = function(param){ 
    // add missing `new`: 
    if(!(this instanceof x)) 
     return new x(param); 

    this.data=param; 

    this.y = function(){ 
     alert(this.data) 
    } 
} 


x.prototype.z = function(){ 
    alert(this.data); 
} 

x(123).y(); 
x(456).z(); 
+0

Я знаю о новой проблеме с ключевым словом. Но мне нужно иметь решение, не используя новые. ИДЕИ? –

+0

извините, если вы не хотите использовать 'new', вы не можете использовать' prototype', поэтому вам нужно будет добавить метод 'z()' ко всем объектам вручную ... – Christoph

+0

добавил пример того, как «скрыть» «новый» и использовать простой вызов функции для создания объекта – Christoph

1

Возможно, и ваша прокомментированная функция z должна работать так, как если вы исправите, как вы создаете x.

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

Edit: К сожалению, я пропустил что-то: Вы упускаете new ключевое слово, ваши примеры должны быть:

new x(123).y(); 
new x(123).z(); 

... и ваш конструктор не должен возвращать this.

Полный пример:

var x = function(param) { 

    this.data=param; 

    // Doesn't have to be in the constructor, and you should 
    // avoid it unless you're doing something with major 
    // data hiding a'la Crockford 
    this.y = function() { 
     alert(this.data) 
    } 
} 

x.prototype.z = function() { 
    alert(this.data); 
} 

new x(123).y(); 
new x(123).z(); 

This is the Crockford article Я уже говорил выше, но опять же, это имеет большие последствия памяти.

+0

Я знаю о проблеме нового ключевого слова. Но мне нужно иметь решение, не используя новые. ИДЕИ? –

+2

Не используйте 'this', если вы не хотите использовать' new'. –

+0

@Saiful: оберните все это в другую функцию, которая выполняет 'new' для вас и возвращает результат. Для этого вам нужно «новое». –

0
function generator(param) { 
    this.data = param; 
    this.y = function() { 
     alert(this.data) 
    } 
} 

generator.prototype.z = function() { 
    alert(this.data); 
} 

x = new generator(3); 
x.y() 
x.z() 

Не уверен, если это то, что вы хотите, но это конструктор с именем generator, который возвращает объект, и прототипный метод определяется вне его с помощью ключевого слова new.

Как другие заявили:

  • вам не нужно возвращать this в конструкторе
  • вы называете это с new ключевое слово
  • все методы, объявленные с this являются открытыми, если вы не используете var в в этом случае они становятся частными
Смежные вопросы