Javascript.RU

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

Требуется помощь
Я новичек в программировании под JS. До этого в основном писал на С под микроконтроллеры, и не сразу получается все понять.
Собственно вопрос вот в чем. Приведу абстрактный код который у меня не работает как надо. Это часть скрипта который загружается в браузере.
//*1
function a()
{

    let selectCallback=1;
    let gFileList;

    a.prototype=
    {
        setSelectCallback: function(value)
	    {
	    	selectCallback=value;
	    }
    }

    //некоторый код который загружает ресурсы с диска используя промисы

	getFilesAndFoldersList(gCurentPath).then((res)=>
		{
			gFileList=res;
		},
		function(err)
		{
			let b=err;
		});
}
//*2
window.addEventListener("load",function() {
   let b=new a();
   b.setSelectCallback(function(a)
       {
          //do something
          let c=a;
       });
});


Собственно вопрос в том, что при первом вызове из "*2" в отладчике показывает что у переменной b в прототипе нет метода setSelectсallback. При втором вызове он есть, но когда используется внутри функции a значение selectCallback остается равно 1. Собственно почему? если я проходя по отладке вижу, что значение переменной seleckCallback в функции a меняется на нужный мне обработчик, но когда я пытаюсь использовать значение переменной изнутри функции оно всегда равно 1.

Сильно не пинайте. Возможно я в принципе неправильно все это пытаюсь сделать, но кучу интернета перерыл ответа на вопрос не нашел.

Последний раз редактировалось rexton, 23.03.2020 в 20:19.
Ответить с цитированием
  #2 (permalink)  
Старый 23.03.2020, 21:07
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,053

Сообщение от rexton
Собственно вопрос в том, что при первом вызове из "*2" в отладчике показывает что у переменной b в прототипе нет метода setSelectсallback.
Это все потому, что вы прототип функции изменяете при её вызове.
JavaScript - интерпретируемый ЯП.

Сообщение от rexton
но когда я пытаюсь использовать значение переменной изнутри функции оно всегда равно 1
Вы, скорее всего, проводите манипуляции над свойством до того, как его значение будет перезаписано. Без упоминаемого кода сложно сказать, что не так.

Попробуйте так:
function someClass() {
    this.selectCallback = 1;
    
    if (!this.gFileList && window.gCurentPath) {
        this.__loadFileList(gCurentPath);
    }
};

someClass.prototype.gFileList = null;

someClass.prototype.__loadFileList = function (directoryPath) {
    if (!directoryPath) {
        return Promise.reject();
    }
    
    return getFilesAndFoldersList(directoryPath).then(res => {
        this.gFileList = res;
    });
};

someClass.prototype.setSelectCallback = function (value) {
    this.selectCallback = value;
};

window.addEventListener('load', function () {
    var someClassInstance = new someClass();
    
    someClassInstance.setSelectCallback(function (a) {
        // do something
        
        let c = a;
    });
});


P.S. от прямого изменения прототипа можно избавиться с помощью синтаксического сахара добавленного в ES6, т.е. объявить класс с помощью ключ. слова «class».

Последний раз редактировалось Nexus, 23.03.2020 в 21:13.
Ответить с цитированием
  #3 (permalink)  
Старый 23.03.2020, 21:53
Новичок на форуме
Отправить личное сообщение для rexton Посмотреть профиль Найти все сообщения от rexton
 
Регистрация: 23.03.2020
Сообщений: 3

Попробовал возникли следующие вопросы:
1. Это общепринятая практика не менять proto функции в ее вызове?
2. Как всегда проблема с this. Он не указывает на someClass. Я хочу использовать переменную selectCallback в обработчике нажатия кнопок, и соответственно this указывает на window а не на someClass. Что делать с этим? bind?

Ну и напоследок, все это я ковыряю на KaiOS (основан на FirefoxOS движок Gecko 48), хотя не думаю, что это имеет принципиальное значение.

С class у меня не сложилось, если правильно помню, там не получается создавать переменные для экземпляра класса.
Ответить с цитированием
  #4 (permalink)  
Старый 23.03.2020, 23:07
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 28,078

Сообщение от rexton
Что делать с этим?
Сообщение от nerv_
перечислю все известные мне способы решения "детских" проблем с this.
https://javascript.ru/forum/dom-wind...tml#post470583
Ответить с цитированием
  #5 (permalink)  
Старый 23.03.2020, 23:07
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,053

Сообщение от rexton
1. Это общепринятая практика не менять proto функции в ее вызове?
Я думаю, что да. Никогда не видел, чтобы прототип класса изменялся в конструкторе. Да и зачем это?

Сообщение от rexton
2. Как всегда проблема с this. Он не указывает на someClass. Я хочу использовать переменную selectCallback в обработчике нажатия кнопок, и соответственно this указывает на window а не на someClass. Что делать с этим? bind?
Покажите, пожалуйста, ваш код.
Скорее всего Вы пытаетесь забить гвоздь отверткой.

Сообщение от rexton
С class у меня не сложилось, если правильно помню, там не получается создавать переменные для экземпляра класса.
Не понял.
Ответить с цитированием
  #6 (permalink)  
Старый 23.03.2020, 23:38
Новичок на форуме
Отправить личное сообщение для rexton Посмотреть профиль Найти все сообщения от rexton
 
Регистрация: 23.03.2020
Сообщений: 3

2 Nexus
1. Это незачем. Просто привычка от C. В вызванной функции делается все, что должно быть сделано, а не кусок кода который загружен в память, нигде не вызывается, но выполняется).
2. Да смысла нет выкладывать весь говнокод. Я просто тренируюсь. После вашей рекомендации вынести proto вне функции с ним все стало нормально, после первого вызова есть нужный метод. this привязал через bind.
3. пробовал писать так:
class a
{
    let b=1;

    c()
    {
        alarm(b);
    }
}

на let b=1; затык, синтаксическая ошибка, и так и не нашел, как сделать переменную для класса которая была бы доступна всем функциям внутри класса (ну как в c++).
А используя функции это возможно.
Ответить с цитированием
  #7 (permalink)  
Старый 24.03.2020, 02:05
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,563

rexton, вы можете объявить все нужные переменные при инициализации класса, например ваш пример выше... Синтаксис ES2020
{

class A {
	b = 1;

	c() {
		alarm(this.b);
	}
}

function alarm(message) {
	alert("⚠️ " + message);
}

const a = new A();
a.c();

}


Если вы хотите использовать более старую спецификацию, то...
{

class A {
	constructor() {
		this.b = 1;
	}

	c() {
		alarm(this.b);
	}
}

function alarm(message) {
	alert("⚠️ " + message);
}

const a = new A();
a.c();

}


Сообщение от rexton
А используя функции это возможно.
Класс — это тоже функция. Т. е. если вы пишете...
class A {
	constructor() {
		let a = 1;
		this.a = 2;
	}
}
то это тоже самое, что...
function A() {
	// if(!new.target) throw new TypeError("Class constructor cannot be invoked without 'new'");
	let a = 1;
	this.a = 2;
}
Отличие в том, что объявление класса при помощи функции-конструктора требует ручной проверки (если практически необходимо; в примере выше закомментировано) на то, что этот конструктор не будет вызываться как функция, а скорей только как конструктор. (А синтаксис класса предполагает такую проверку автоматически)

Последний раз редактировалось Malleys, 24.03.2020 в 02:22.
Ответить с цитированием
Ответ



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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Требуется помощь с прошивкой баннеров HTML5 Canvas kambodge Работа 0 08.07.2016 13:55
Требуется помощь bboulevard Ваши сайты и скрипты 14 02.12.2013 15:47
Работа с массивами. Требуется помощь. Кристи Общие вопросы Javascript 3 08.02.2011 17:00
Требуется помощь. Дмитрий Котов Работа 9 22.02.2010 19:02
Цитирование текста в комментариях. Требуется помощь. shinjuku Общие вопросы Javascript 3 07.07.2008 13:19