Как получить внешнюю ссылку "this" в JavaScript

Итак, у меня есть класс, который позволяет называть его A. Для этого класса я написал несколько функций, которые я могу назвать так:

var a = new A();
a.getSomething();
a.putSomething();
a.delSomething();

И так далее. Теперь я подумал, что я бы немного его организовал. Поэтому он не стал бы слишком суматошным и выглядел бы как-то вроде этого:

a.something.get();
a.something.put();
a.something.del();

И вот как я пытался добиться этого:

A.prototype.something = {
  get: function(){...},
  put: function(){...},
  del: function(){...}
};

Но для этих функций (get, put и del) по-прежнему необходимо обращаться к общим объектам/функциям, найденным в A, поэтому мне нужна ссылка на A, но я не знаю, как это можно достичь.

Один из вариантов, который я нашел, выглядит следующим образом:

A.prototype.something = function(){
  var that = this;
  return {
    get: function(){...},
    ...
  };
}; 

И "это" будет использоваться в этих (get, put и del) функциях вместо 'this'. Но это означало бы, что я должен был бы назвать эти функции таким образом:

a.something().get();
...

Что мне не очень нравится. Так что я могу организовать эти вещи так, как я изначально планировал?

Ответ 1

Итак, у меня есть класс

Javascript не имеет классов. У этого есть наследование прототипа, которое может эмулировать классы в ограниченной степени, но это не стоит исключительно ради эмулирования классов. Гораздо лучше сделать оптимальное использование встроенных языковых функций, а не пытаться подражать javascript другому языку.

Итак, у вас есть конструктор...

Я написал несколько функций, которые я могу назвать так:

var a = new A();
a.getSomething();
a.putSomething();
a.delSomething();

Предположительно, эти методы находятся на A.prototype.

И так далее. Теперь я подумал, что я бы немного его организовал. Поэтому он не стал бы слишком суматошным и выглядел бы как-то вроде этого:

a.something.get();
a.something.put();
a.something.del();

Это не менее захламлено (для меня). Я предполагаю, что есть что-то общее, что что-то сделано, и что его методы get, put и т.д. Хотят работать не на чем-то.

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

Следующее похоже, но избавляет от замыкания и ставит методы на Something.prototype для некоторой эффективности:

function A(name) {
    this.name = name;
    this.something = new Something(this);
}


function Something(that){
    this.that = that;
}

Something.prototype.get = function() {
    return this.that.name;
}
Something.prototype.put = function(prop, value) {
    this.that[prop] = value;
}

var a = new A('a');

alert(a.something.get());     // a
a.something.put('name', 'z');
alert(a.something.get());     // z

Таким образом, вы можете иметь несколько somethings, каждый с различными методами put, get и т.д. Но вмешательство чего-то объекта - это просто устройство, которое использует больше памяти (возможно, крошечную сумму) и требует дополнительного символа. Упрощен, чтобы сохранить что-то на A.prototype и не нужно вводить дополнительную точку (.).

Ответ 2

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

Вам нужно сделать это в конструкторе:

function A() {
    var that = this;
    this.something = { 
       get: function(){...}, 
       ... 
    };
}

Ответ 3

function A() {
  this.something = this;
}
A.prototype = {
  get: function(){...},
  put: function(){...},
  del: function(){...}
};

поэтому:

a.something.get();
a.something.put();
a.something.del();