Как правильно получить доступ к внешнему объекту из внутреннего в JavaScript?

Есть следующий код:
function mock() {
	this.val = 'val';
	this.log = {
		start: function() {
			this.timer = setInterval(function() {
				console.log(this.val);
			}.bind(this), 1000);
		}.bind(this),
		stop: function() {
			clearInterval(this.timer);
			delete this.timer;
		}.bind(this)
	};
}


Впоследствии в строке console.log(this.val); предполагается доступ к внешнему объекту (то есть к mock). Сейчас я использовал bind(this) чтобы передать контекст во вложенные функции. Как правильно было бы написать подобное в парадигме JS так, чтобы в строке вида console.log(this.val) я мог получить нормальный доступ к внешнему (mock) объекту, и при этом чтобы интервал прикреплялся именно к вложенному объекту log(и был доступен через this в log'е) а не к mock? Насколько я понял тут либо надо передавать что-то через аргумент в start() либо каким-то образом сделать замыкание (но что именно замкнуть???). Но я все равно не понимаю, как бы это сделал человек который программирует на JS уже не один год и который умеет на этом языке думать) подскажите плз, javascript-ниндзи
ЗЫ.: Сам только перелез с пыхи на JS под Ноду. Не знаю насколько код выше выглядит адекватным, не судите строго
  • Вопрос задан
  • 671 просмотр
Решения вопроса 1
У вас же this везде ссылается на корневой объект, значит ничего не мешает получить вложенный и работать с его свойствами:

function Mock() {
    this.val = 'val';
    this.log = {
        start: function() {
            this.log.timer = setInterval(function() {
                console.log(this.val);
            }.bind(this), 1000);
        }.bind(this),
        stop: function() {
            clearInterval(this.log.timer);
            delete this.log.timer;
        }.bind(this)
    };
}

Но конечно лучше просто разделить сущности:

function Timer(handler, interval) {
    this.handler = handler;
    this.interval = interval;
}

Timer.prototype.start = function () {
    this.timer = setInterval(this.handler, this.interval);
};

Timer.prototype.stop = function () {
    clearInterval(this.timer);
    delete this.timer;
};

function Mock() {
    this.val = 'val';
    this.log = new Timer(function () {
        console.log(this.val);
    }.bind(this), 1000);
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@vshvydky
если я правильно понимаю, то вы хотите по вызову this.val в любом месте кода получать значение объекта , но это же не правильно.
Ваш случай следующий:
let m = new mock();
m.log.start();
m.log.stop();

про this в браузере this вне какого-либо объекта будет ссылаться на window
в ноде на объект ноды, который в себе много чего содержит (global, module, process и тп)
Или вы про это?
function mock(number) {
  this.number = number;
  this.val = 'val';
  this.log = {
    start: function() {
      this.timer = setInterval(function() {
        console.log(this.number, ": ", this);
      }.bind(this), 1000);
    }.bind(this),
    stop: function() {
      clearInterval(this.timer);
      delete this.timer;
    }.bind(this)
  };
}

m = new mock('1')
> mock {number: "1", val: "val", log: Object}
n = new mock('2')
>mock {number: "2", val: "val", log: Object}
m.log.start(); n.log.start()

VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
m.log.stop(); n.log.stop()
Ответ написан
Комментировать
То что вы ищите похоже на стрелочные функции в ES6.
Я бы сделал так:
function mock() {
  this.val = 'val';
  this.startlog = () => {
     this.timer = setInterval(() => {
        console.log(this.val);
      }, 1000)
  };
  this.stopLog = () => {
      clearInterval(this.timer);
      delete this.timer;
  }
}

Или с классами:
class Mock {
   constructor() {
      this.val = 'val';
   }

   startlog() {
     this.timer = setInterval(() => {
        console.log(this.val);
      }, 1000)
  }

   stopLog() {
      clearInterval(this.timer);
      delete this.timer;
  }

}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы