Инкапсуляция функции JavaScript вне объекта - PullRequest
1 голос
/ 05 октября 2009

Пожалуйста, смотрите следующий скрипт:

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()

Когда я звоню x (123) .y () , появляется сообщение 123 . Функция y () объявлена ​​внутри x ()

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

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

Ответы [ 3 ]

3 голосов
/ 05 октября 2009

Вы пропускаете new при звонке x(). В противном случае this в теле функции будет ссылаться на глобальный объект (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();
1 голос
/ 05 октября 2009

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

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

Редактировать: Извините, я что-то упустил: Вам не хватает ключевого слова 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();

Это статья Крокфорда Я упоминал выше, но, опять же, это имеет большое значение для памяти.

0 голосов
/ 05 октября 2009
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, в этом случае они становятся приватными
...