2010-03-11 3 views
8

Вот учебник стандартный способ описания «класс» или функцию конструктора в JavaScript, прямо из Definitive Guide на JavaScript:методы Прикрепление к прототипу из функции конструктора

function Rectangle(w,h) { 
    this.width = w; 
    this.height = h; 
} 
Rectangle.prototype.area = function() { 
    return this.width * this.height; 
}; 

Я не например, манипулирование прототипами болтающихся здесь, поэтому я пытался придумать способ инкапсуляции определения функции для area внутри конструктора. Я придумал это, что я не рассчитывать на работу:

function Rectangle(w,h) { 
    this.width = w; 
    this.height = h; 
    this.constructor.prototype.area = function() { 
     return this.width * this.height; 
    }; 
} 

Я не ожидал, что это работает, потому что this ссылка внутри функции area должна быть направлена ​​к самим area функции, так что я не имел бы доступа к width и height от this. Но, оказывается, я это делаю!

var rect = new Rectangle(2,3); 
var area = rect.area(); // great scott! it is 6 

Некоторые дальнейшие испытания подтвердили, что this ссылки внутри функции area была на самом деле ссылка на объект под строительством, а не сама функция области.

function Rectangle(w,h) { 
    this.width = w; 
    this.height = h; 
    var me = this; 
    this.constructor.prototype.whatever = function() { 
     if (this === me) { alert ('this is not what you think');} 
    }; 
} 

Оказывается, предупреждение всплывает, и this это точно строящийся объект. и так, что здесь происходит? Почему this не this Я ожидаю, что это будет?

+3

Если у вас есть сто прямоугольников, вы собираетесь повторно использовать этот прототип метода сто раз. Хорошо, что у вас есть только один метод ... – kennebec

+0

Это хороший момент. –

ответ

5

Я думаю, что правильный ответ в том, что вы не должны делать это, потому что, как Kennebec сказал в комментарии:

Если у вас есть сто прямоугольников, вы собираетесь переобъявить этот метод прототипа сто раз ,

1

Я думал, что «это» всегда ссылается на объект, против которого была вызвана функция.

+1

Я думаю, что официальный ответ «это зависит». –

+0

Чтобы уточнить, 'this' ссылается на объект, через который эта функция была вызвана, когда функция используется как метод для объекта. Здесь не так. В этом случае функция вызывается как функция, а не метод для объекта, поэтому 'this' действительно должен ссылаться на глобальный объект. –

0

Что это означает, определяется при запуске кода.

Вот простой способ выяснить, что это такое.

Если вы используете '.' для ссылки на функцию, «это» будет ссылкой на все, что находится на левой стороне «.».

(Это не учитывает .call и .Нанесите)

var myFn = function() { 
return this.name + ' called me'; 
}; 

var me = { 
name : 'oatkiller', 
shoutOut : myFn 
}; 

var you = { 
name : 'Matthew', 
shoutOut : myFn 
}; 

// im on the left of the dot, so this points to me 
me.shoutOut(); // 'oatkiller called me' 

// youre on the left of the dot, so this points to you 
you.shoutOut(); // 'Matthew called me' 
1

Значение this зависит, как была вызвана функция:

  • this обычно относится к объекту функция является вызывается из во время выполнения, например когда он называется ob.foo(), this в foo будет ссылаться на ob.
  • Если функция вызывается в режиме без объекта, например, только foo(), this относится к глобальной переменной (верхнему объекту, который содержит все другие глобальные переменные в вашей программе js).
  • И в .call() и .apply(), объект, к которому относится this.

Теперь, если вам нужен способ указать объект на функцию, в которой была создана ваша функция (т., 2-й уровень this во время создания), то вам нужно будет переименовать более глубокий this, чтобы он сиял через видимый в данный момент. Если это ясно, как грязь, это должно помочь прояснить немного:

function outside() { 
    // Here, 'this' refers to the object outside() is called with. 
    // Let's "rename" this, to make it visible to inside functions. 
    var that = this, 
     private = 42; 

    return { 
     inside: function { 
      // here, 'this' refers to the object inside() is called with, 
      // it is hiding outside's this. 
      // Also, 'that' refers to the object outside() was called with, 
      // *at the time* outside was called and inside was created. 
      // Notice that you can see 'private' 
      // (but nobody outside of 'outside()) can! 
      return private; 
     } 
    } 
} 

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

0

Я думаю, что вы действительно близки к заключительному примеру. Как об использовании привилегированного метода:

function Rectangle(w,h) { 
    this.width = w; 
    this.height = h; 
    var that = this; 
    this.area = function() { 
    return that.width * that.height; 
    } 
} 

var rect = new Rectangle(2,3); 
console.log(rect.area()); 

Crockford's "Private Members in JavaScript" Смотрите для получения дополнительной информации.

Смежные вопросы