Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 23.01.2019, 20:52
Аспирант
Отправить личное сообщение для Tipylja Посмотреть профиль Найти все сообщения от Tipylja
 
Регистрация: 17.04.2017
Сообщений: 72

Стрелочная функция в объекте
Здравствуйте, есть вот такая функция-модуль:
var paralax = ( () => {
		const
			bg = document.querySelector('.header__bg')
			,user = document.querySelector('.header__me')
			,text = document.querySelector('.header__img-portfolio');
		
		
		return {
			move: function (block, windowScroll, rateVaue) {
				var shift = windowScroll / -rateVaue + '%';
				var style = block.style;
	
				style.top = shift;
			},
			init: function (windowScroll)  {				
				this.move(bg, windowScroll, 45);
				
			}
	}
	
	})();

Она возвращает два метода move и init, в таком виде она работает, но если эти методы описывать через стрелочные функции то я получаю ошибку
this.move is not a function
Я так понимаю теряется контекст в таком случае? Подскажите пожалуйста, как этого избежать?
Ответить с цитированием
  #2 (permalink)  
Старый 23.01.2019, 21:15
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,123

Tipylja,
вариант...
const paralax = (() => {
const   bg = document.querySelector('.header__bg'),
        user = document.querySelector('.header__me'),
        text = document.querySelector('.header__img-portfolio'),
        move = (block, windowScroll, rateVaue) => {
            const shift = windowScroll / -rateVaue + '%';
            const style = block.style;
            style.top = shift;
        },
        init = (windowScroll) => {
            move(bg, windowScroll, 45);
        };

    return {
        move,
        init
    }

})();
Ответить с цитированием
  #3 (permalink)  
Старый 23.01.2019, 22:17
Аватар для MallSerg
Профессор
Отправить личное сообщение для MallSerg Посмотреть профиль Найти все сообщения от MallSerg
 
Регистрация: 07.03.2011
Сообщений: 1,138

Сообщение от Tipylja Посмотреть сообщение
this.move is not a function
Я так понимаю теряется контекст в таком случае? Подскажите пожалуйста, как этого избежать?
Просто нужно разобраться как работает this в javaScript.
paralax.init.move - не существует что и приводит к ошибке

this в JS динамически заменяется в момент вызова функции и всегда указывает в контексте какого объекта он исполняется. В отличии от некоторых языков программирования где он является константным указателем на экземпляр класса.
<script>
function GetName() { return this.name; }
 
var vasa = {name: "Вася"};
var lena = {name: "Лена"};
var petia = {name: "Петя"};
 
vasa.gn = GetName;
lena.gn = GetName;
petia.gn = GetName;
 
document.write ( vasa.gn() + "<br>") ;
document.write ( lena.gn() + "<br>") ;
document.write ( petia.gn() + "<br>") ;
</script>

В JS очень важно понимать как создается и работает контекст исполнения функции (текущая область видимости переменных).
Ответить с цитированием
  #4 (permalink)  
Старый 23.01.2019, 23:17
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от Tipylja
Подскажите пожалуйста, как этого избежать?
Используйте синтаксический сахар для методов объекта...
const paralax = (() => {
	const
	  bg   = document.querySelector('.header__bg')
	, user = document.querySelector('.header__me')
	, text = document.querySelector('.header__img-portfolio')


	return {
		move(block, windowScroll, rateVaue) {
			const shift = windowScroll / -rateVaue + '%';
			const style = block.style;

			style.top = shift;
		},

		init(windowScroll)  {				
			this.move(bg, windowScroll, 45);
		}
	}
})();
Ответить с цитированием
  #5 (permalink)  
Старый 24.01.2019, 14:13
Аспирант
Отправить личное сообщение для Tipylja Посмотреть профиль Найти все сообщения от Tipylja
 
Регистрация: 17.04.2017
Сообщений: 72

Спасибо за ответы. Но все работает и так, в приведенном мною примере, если функции описывать классически путем, а вот если использовать стрелочный синтаксис, то нет.
На сколько я понимаю, то в классическом виде this указывает на возвращаемый объект, который по замыканию видит переменные внутри модуля и методы внутри себя this.move и this.init, но если объявлять функции через стрелочный синтаксис, то this указывает на window, а там никаких move и init нет.
И вопрос в том, как быть, если хочется уйти от классического объявления функции и перейти полностью на стрелочные
Ответить с цитированием
  #6 (permalink)  
Старый 24.01.2019, 14:23
Аспирант
Отправить личное сообщение для Tipylja Посмотреть профиль Найти все сообщения от Tipylja
 
Регистрация: 17.04.2017
Сообщений: 72

Сообщение от рони Посмотреть сообщение
Tipylja,
вариант...
Так работает, спасибо!
Ответить с цитированием
  #7 (permalink)  
Старый 25.01.2019, 01:49
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от Tipylja
Но все работает и так, в приведенном мною примере, если функции описывать классически путем, а вот если использовать стрелочный синтаксис, то нет.
«Стрелочный синтаксис» — это та же самая функция, представитель класса Function. При инициализации ей не назначается внутреннее свойство [[Construct]]. Контекст такой функции связан с this того места, где она создавалась. Т. е. () => {} можно представить как (function() {}).bind(this). Да, в вашем примере this указывает на глобальный объект, поскольку в том месте, где создавалась такая функция, this указывал на глобальный объект. Если бы, например, вы создали такую функцию внутри конструктора Foo, то this внутри неё указывал бы на представителя класса Foo (при соответствующей инициализации new Foo)

Сообщение от Tipylja
И вопрос в том, как быть, если хочется уйти от классического объявления функции и перейти полностью на стрелочные
«Стрелочные функции» не могут быть использованы как конструктор, лучше всего подходят для функций без методов, не имеют собственного объекта arguments, поэтому в теле стрелочных функций arguments будет ссылаться на переменную в окружающей области, вызов стрелочных функций с помощью методов call() или apply(), даже если передать аргументы в эти методы, не влияет на значение this, подходят для функционального программирования. Важно понимать, когда вам нужно, чтобы функция содержала собственный контекст this, а когда нет.

В вашем примере нужно, чтобы функция содержала собственный контекст this, в том решении, которое вам привёл рони, вы всё-таки не можете использовать this, вы не можете вызывать методы в контексте, у вас нет внутри метода ссылки на объект. В моём примере выше (пост №4) я вам показал, как можно избежать потери контекста. (+ БОНУСЫ! не нужно печатать имена методов два раза, не нужно печатать «стрелки»)

Сообщение от Tipylja
хочется уйти от классического объявления функции и перейти полностью на стрелочные
Ограничивая себя таким образом, не нужно забывать, что стрелочная функция является только малой частью того, что может полностью инициализированная функция.

Каким бы образом функция синтаксически не записывалась, она принимает аргументы, производит какие-либо действия, и возвращает результат. И всё!

А вы когда либо задумывались о том, что может существовать нечто, напоминающее функцию, оно тоже принимает аргументы, производит действия, останавливается и возвращает результат. Однако может обратно вернуться и продолжить выполнение дальше! Опять возвратить результат. А представьте две такие функции, которые переходят из одной в другую! Вот это бы я назвал «уйти от классического объявления функции»
Ответить с цитированием
  #8 (permalink)  
Старый 02.08.2019, 16:10
Интересующийся
Отправить личное сообщение для Трудяга Посмотреть профиль Найти все сообщения от Трудяга
 
Регистрация: 30.07.2019
Сообщений: 19

переделать в стрелочную функцию
Добрый день, возникла проблемка( нужно переделать функцию в стрелочную, нижнюю часть я сделал а при изменении верхней, консоль ругается что не переданы аргументы.

<script>
function sum() {
const params = Array.prototype.slice.call(arguments);

if (!params.length) return 0;

return params.reduce((prev, next) => prev + next);
}
console.log(sum(1, 2, 3, 4)); // 10
console.log(sum()); // 0
</script>
Ответить с цитированием
  #9 (permalink)  
Старый 02.08.2019, 19:48
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от Трудяга
нижнюю часть я сделал а при изменении верхней, консоль ругается что не переданы аргументы.
В сообщении выше же сказано, что «стрелочные функции»... не имеют собственного объекта arguments.

Короткий вариант...

function sum(...params) {
	if(!params.length) return 0;

	return params.reduce((prev, next) => prev + next);
}

console.log(sum(1, 2, 3, 4));// 10
console.log(sum());// 0


Длинный вариант...
const sum = (...params) => {
	if(!params.length) return 0;

	return params.reduce((prev, next) => prev + next);
}
console.log(sum(1, 2, 3, 4));// 10
console.log(sum());// 0


Более короткий вариант...
const sum = (...params) => params.reduce((prev, next) => prev + next, 0);
console.log(sum(1, 2, 3, 4));// 10
console.log(sum());// 0

Последний раз редактировалось Malleys, 02.08.2019 в 19:51.
Ответить с цитированием
Ответ



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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Функция отрабатывает, а значение не то... the_little Общие вопросы Javascript 2 30.07.2018 12:25
Функция вызывается несколько раз KiberQ Общие вопросы Javascript 11 01.03.2017 15:45
не вызывается функция при изменении option soft4you Общие вопросы Javascript 1 23.07.2014 17:41
AJAX функция для новых html-элементов broadcast77 AJAX и COMET 25 03.03.2014 14:01
Два события на одном объекте zzzzzz Элементы интерфейса 9 29.05.2013 13:41