Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 27.08.2011, 14:04
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Выяснить, что функция вызвана в режиме конструктора
Есть идеи, как внутри F различать способы вызова?

function F() {}

new F;
F.call(new F);
F();


обычно делаю так
function F() {
    if (this.constructor == F) {
        return 1;
    }
    return 2;
}


Но понадобилось отделить вариант с F.call(obj), и вот когда obj - это объект, созданный с помощью F, такая проверка не подходит. Нужно отделить способы запуска [[Construct]] и [[Call]].
Ответить с цитированием
  #2 (permalink)  
Старый 27.08.2011, 14:20
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

я не вижу возможного решения.

т.е. как разделить эти два вызова ?
function F(){ this.a=function(){}; }

var a = new F;

var b = new F;

a.a();
// и 
F.call( b ).a();
Ответить с цитированием
  #3 (permalink)  
Старый 27.08.2011, 14:24
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Ну решение есть:
function F() {
	if (this.constructor == F) {
		if (this._constructed) {
			alert("F.call(new F)");
			return null;
		}
		this._constructed = true;
		return this;
	}
	return null;
}

new F;

F.call(new F);

F.call({});

F();

Просто может я торможу и еще как-то проще/лучше/надежнее можно сделать. Не очень хочется иметь ненужное enumerable-свойство в каждом объекте.

Последний раз редактировалось Octane, 27.08.2011 в 14:31.
Ответить с цитированием
  #4 (permalink)  
Старый 27.08.2011, 14:36
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Сообщение от Octane Посмотреть сообщение
Просто может я торможу и еще как-то проще/лучше/надежнее можно сделать. Не очень хочется иметь ненужное enumerable-свойство в каждом объекте.
Object.defineProperty ? ie9+
Ответить с цитированием
  #5 (permalink)  
Старый 27.08.2011, 14:41
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Да смысл, надо будет помнить о дополнительных проверках для старых браузеров.
Ответить с цитированием
  #6 (permalink)  
Старый 27.08.2011, 15:00
Профессор
Отправить личное сообщение для Sweet Посмотреть профиль Найти все сообщения от Sweet
 
Регистрация: 16.03.2010
Сообщений: 1,618

Сообщение от Octane
Не очень хочется иметь ненужное enumerable-свойство в каждом объекте.
Можно не создавать спецальное свойство, а смотреть на какое-нибудь, какое есть
Ответить с цитированием
  #7 (permalink)  
Старый 27.08.2011, 20:13
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

а зачем их отличать? constructor - обычный метод, который предназначен для инициализации объекта. запись ( new F( 1, 2, 3 ) ) - это просто грубо говоря более короткая запись следующей ( var obj= {}; obj.__proto__= F.prototype; return obj.constructor( 1, 2, 3 ) || obj )
__________________
.ня
Ответить с цитированием
  #8 (permalink)  
Старый 27.08.2011, 20:49
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

function F(x) {
	if (this.constructor == F) {
		this.x = x;
	}
	return this.x;
}

var f = new F(3), obj = {x: 5};

alert(f.x); //3

alert(F.call(obj)); //5
*!*
alert(F.call(f)); //ожидаем получить 3, а будет undefined
*/!*
Ответить с цитированием
  #9 (permalink)  
Старый 27.08.2011, 21:01
Профессор
Отправить личное сообщение для Sweet Посмотреть профиль Найти все сообщения от Sweet
 
Регистрация: 16.03.2010
Сообщений: 1,618

В конкретном примере было бы уместно проверять, передан ли аргумент:
if (this.constructor == F && arguments.length > 0) {
Ответить с цитированием
  #10 (permalink)  
Старый 27.08.2011, 21:49
Аватар для B@rmaley.e><e
⊞ Развернуть
Отправить личное сообщение для B@rmaley.e><e Посмотреть профиль Найти все сообщения от B@rmaley.e><e
 
Регистрация: 11.01.2010
Сообщений: 1,810

Обыграть то, что в случае вызова через new F сначала создается пустой объект, а потом уже к нему применяется конструктор. В случае с call'ом к объекту уже применён конструктор.
function F(x) {
	if (this.constructor == F && this.sealed === undefined) {
		this.x = x;
	}
	this.sealed = true;
	return this.x;
}

var f = new F(3), obj = {x: 5};

alert(f.x); //3

alert(F.call(obj)); //5
alert(F.call(f)); //ожидаем получить 3, а будет 3
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Получить элемент, на котором была вызвана функция barcelona Общие вопросы Javascript 15 06.07.2013 03:44
О фрилансе (Личный опыт) free Оффтопик 105 18.08.2011 17:02
Поюзайте хомячка Nanto Ваши сайты и скрипты 30 06.06.2011 22:16
Выполняется функция, а все что написано после нее игнорируется, libinstyle Элементы интерфейса 4 24.03.2010 16:44
есть ли стандартная функция вывода сожержимого массива что то вроди print_r в PHP??? mazovski Events/DOM/Window 4 20.08.2009 12:52