18.09.2017, 01:12
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,068
|
|
malinovsky,
"use strict"
class Game
{
constructor()
{
let self = this;
this.loop = function(time) {
console.log(time);
requestAnimationFrame(self.loop);
};
this.loop();
}
}
var game = new Game();
"use strict"
class Game
{
constructor()
{
this.loop = function(time) {
console.log(time);
requestAnimationFrame(this.loop);
}.bind(this);
this.loop();
}
}
var game = new Game();
Последний раз редактировалось рони, 18.09.2017 в 01:15.
|
|
19.09.2017, 16:01
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
Сообщение от malinovsky
|
Почему в стрелочных функциях this ведет себя не так как в обычных?
|
очевидно это одно из их отличий
|
|
19.09.2017, 19:41
|
|
Профессор
|
|
Регистрация: 07.03.2011
Сообщений: 1,127
|
|
Сообщение от Rise
|
очевидно это одно из их отличий
|
Тут даже дело не в this а в том что на каждый вызов функции создается контекст (окружение) для исполнения этой функции хотя в этом редко бывает реальная необходимость. Это настоящий удар ниже пояса для производительности. Вот в новом стандарте и ввели способ это обойти вместо создания нового контекста используется уже существующий в котором описывается стрелочная функция а поведение this это следствие отсутствия нового контекста исполнения. И как еще одно следствие в некоторых случая стрелочные функции могут быть в разы быстрее.
|
|
19.09.2017, 20:59
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
MallSerg,
чем докажешь что нет своего this которому присвоен this из замыкания?
|
|
19.09.2017, 22:56
|
|
Профессор
|
|
Регистрация: 07.03.2011
Сообщений: 1,127
|
|
Сообщение от Rise
|
MallSerg,
чем докажешь что нет своего this которому присвоен this из замыкания?
|
Я не понял вопроса =(.
this это ключевое слово в JavaScript которое на этапе лексического разбора заменяется на ссылку на вполне конкретный объект. Это поведение подробно описано в спецификации.
Функции в JS это объекты первого типа т.е. их можно использовать как обычные переменные (сохранять передавать как параметры и.т.д.) функции в JS могут оперировать не только с параметрами и локальной областью видимости но и с переменными во внешней области видимости. Что заставляет интерпретатор при создании каждой функции в JS создавать [[skope]] ссылка на который есть в каждой функции.
Если бы механизма сохранения внешнего окружения не было то у сохраненной или же переданной функции не было бы доступа к внешним переменным.
Именно создание уникального окружения (LexicalEnvironment) для каждой функции и делает возможным механизм замыкания.
this заменяется на ссылку на обычный object в котором нет ни явных ни скрытых ссылок на контекст в котором исполняется функция.
Т.е. если совсем грубо и на пальцах написал ключевое слово function вне глобальной области видимости получи оверхед на создание окружения для функции.
Раньше приходилось писать универсальную функцию и раскидывать логику условным ветвлением сейчас можно использовать стрелочные функции отчего код становится проще и понятнее и быстрее.
|
|
20.09.2017, 00:33
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
Сообщение от MallSerg
|
на каждый вызов функции создается контекст (окружение) для исполнения этой функции
|
Сообщение от MallSerg
|
Вот в новом стандарте и ввели способ это обойти вместо создания нового контекста используется уже существующий
|
Сообщение от MallSerg
|
создание уникального окружения (LexicalEnvironment) для каждой функции и делает возможным механизм замыкания
|
Сообщение от MallSerg
|
function вне глобальной области видимости получи оверхед на создание окружения для функции
|
бла бла бла, о каком окружении/контексте ты говоришь? о замыкании? но стрелочные функции способны делать замыкание также как и обычные функции, а по твоей логике нет.
let a = (() => {
let b = 7;
return () => { alert(b) }
})();
a();
И в замыкании функции остаются только те переменные из окружения на которые есть ссылки внутри функции, а не все существующие в окружении ее объявления как ты думаешь...
Последний раз редактировалось Rise, 20.09.2017 в 00:38.
|
|
10.10.2017, 21:08
|
Интересующийся
|
|
Регистрация: 07.09.2017
Сообщений: 14
|
|
Rise,
посмотри пожалуйста:
class Game
{
constructor(canvas) {
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.world = new Set();
this._last = 0;
this.count = 0;
this.objPlayer = new Player(this.canvas.width/2-30, this.canvas.height-30, 30, 20, "rgb(173, 105, 82)", 200);
this.world.add(this.objPlayer);
this.world.add(new Line(0, 0, 600, 5, "rgb(36, 177, 219)"));
this.world.add(new Line(0, 395, 600, 5, "rgb(36, 177, 219)"));
console.log(this.objPlayer);
this.lastObjShot = false;
this._step = (now) => {
this._loop = requestAnimationFrame(this._step);
this.delta = Math.min(now - this._last, 100) / 1000;
this._last = now;
this.shipsGenerator();
this.shotsGenerator();
this.update();
this.render();
};
this._step();
}
update() {
for (let entity of this.world) if (entity.update) entity.update(this);
}
render() {
this.ctx.fillStyle = "rgb(36, 177, 219)";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
for (let entity of this.world) if (entity.render) entity.render(this);
}
collide(entity1, type) {
for (let entity2 of this.world) {
if (entity1 != entity2 &&
entity2.type & type &&
entity1.positionX < entity2.positionX + entity2.sizeX &&
entity1.positionX + entity1.sizeX > entity2.positionX &&
entity1.positionY < entity2.positionY + entity2.sizeY &&
entity1.sizeY + entity1.positionY > entity2.positionY) return true;
}
return false;
}
stop()
{
if (this._loop) this._loop = cancelAnimationFrame(this._loop);
}
shipsGenerator() {
if(this.count > 10) {
this.world.add(new Ship(Math.random() * 590|0, 5, 10, 10, "rgb(22, 105, 67)", 100));
this.count = 0;
}
this.count++;
}
shotsGenerator() {
if(keyEvent.space) {
if(this.lastObjShot) {
if(this.lastObjShot.positionY+7 < 375) {
this.lastObjShot = new Shot(this.objPlayer.positionX+11, 375, 7, 7, "rgb(173, 105, 82)", 100);
this.world.add(this.lastObjShot);
}
} else {
this.lastObjShot = new Shot(this.objPlayer.positionX+11, 375, 7, 7, "rgb(173, 105, 82)", 100);
this.world.add(this.lastObjShot);
}
}
}
}
class Rect
{
constructor(positionX, positionY, sizeX, sizeY, color, vel) {
this.positionX = positionX;
this.positionY = positionY;
this.sizeX = sizeX;
this.sizeY = sizeY;
this.color = color;
this.vel = vel || false;
}
render(game) {
game.ctx.fillStyle = this.color;
game.ctx.fillRect(this.positionX, this.positionY, this.sizeX, this.sizeY);
}
}
const PLAYER = 1, SHIP = 2, SHOT = 4, LINE = 8;
class Player extends Rect
{
constructor(positionX, positionY, sizeX, sizeY, color, vel) {
super(positionX, positionY, sizeX, sizeY, color, vel);
Object.assign(this, { type: PLAYER });
}
update(game) {
if(keyEvent.left) {
this.positionX -= this.vel * game.delta;
}
if(keyEvent.right) {
this.positionX += this.vel * game.delta;
}
if (game.collide(this, PLAYER | SHIP | LINE )) game.stop();
}
}
class Ship extends Rect
{
constructor(positionX, positionY, sizeX, sizeY, color, vel) {
super(positionX, positionY, sizeX, sizeY, color, vel);
Object.assign(this, { type: SHIP });
}
update(game) {
this.positionY += this.vel * game.delta;
if (game.collide(this, PLAYER | SHOT | LINE )) game.world.delete(this);
}
}
class Shot extends Rect
{
constructor(positionX, positionY, sizeX, sizeY, color, vel) {
super(positionX, positionY, sizeX, sizeY, color, vel);
Object.assign(this, { type: SHOT });
}
update(game) {
this.positionY -= this.vel * game.delta;
if (game.collide(this, SHIP | SHOT | LINE )) game.world.delete(this);
}
}
class Line extends Rect
{
constructor(positionX, positionY, sizeX, sizeY, color, vel) {
super(positionX, positionY, sizeX, sizeY, color, vel);
Object.assign(this, { type: LINE });
}
}
const keyEvent = {
left : false,
right : false,
space : false
};
window.onkeydown = function(e) {
switch(e.keyCode) {
case 37 : keyEvent.left = true; break;
case 39 : keyEvent.right = true; break;
case 32 : keyEvent.space = true; break;
}
};
window.onkeyup = function(e) {
switch(e.keyCode) {
case 37 : keyEvent.left = false; break;
case 39 : keyEvent.right = false; break;
case 32 : keyEvent.space = false; break;
}
};
const game = new Game(document.getElementById('canvas'));
|
|
11.10.2017, 05:36
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
malinovsky,
class Player extends Rect {
constructor(options) {
Object.assign(this, { rate: 0.4, delay: 0 }, options);
}
update(game) {
this.delay -= game.delta;
if (keyEvent.space && this.delay < 0) {
this.delay = this.rate;
game.world.add(new Shot(this.x, this.y, 7, 7, 'red', 100));
}
}
}
class Ship extends Rect {
constructor(options) {
Object.assign(this, { rate: 0.8, delay: 0 }, options);
}
update(game) {
this.delay -= game.delta;
if (this.delay < 0) {
this.delay = this.rate;
game.world.add(new Shot(this.x, this.y, 7, 7, 'green', -100));
}
}
}
class Attack {
constructor(options) {
Object.assign(this, { size: 10, rate: 0.5, delay: 0 }, options);
}
update(game) {
this.delay -= game.delta;
if (this.delay < 0) {
this.delay = Math.random() * this.rate;
game.world.add(new Ship(Math.random() * 590, 5, 10, 10, 'green', 100));
if (!--this.size) game.world.delete(this);
}
}
}
|
|
11.10.2017, 22:26
|
Интересующийся
|
|
Регистрация: 07.09.2017
Сообщений: 14
|
|
Rise,
this.delay -= game.delta; // NaN - а почему?
пока сделал так:
class Game
{
constructor(canvas) {
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.world = new Set();
this._last = 0;
this.count = 0;
this.world.add(new Player(this.canvas.width/2-30, this.canvas.height-30, 30, 20, "rgb(173, 105, 82)", 200));
this.world.add(new Attack(50));
this.world.add(new Line(0, 0, 600, 5, "rgb(36, 177, 219)"));
this.world.add(new Line(0, 395, 600, 5, "rgb(36, 177, 219)"));
this.lastObjShot = false;
this._step = (now) => {
this._loop = requestAnimationFrame(this._step);
this.delta = Math.min(now - this._last, 100) / 1000;
this._last = now;
this.update();
this.render();
};
this._step();
}
update() {
for (let entity of this.world) if (entity.update) entity.update(this);
}
render() {
this.ctx.fillStyle = "rgb(36, 177, 219)";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
for (let entity of this.world) if (entity.render) entity.render(this);
}
collide(entity1, type) {
for (let entity2 of this.world) {
if (entity1 != entity2 &&
entity2.type & type &&
entity1.x < entity2.x + entity2.w &&
entity1.x + entity1.w > entity2.x &&
entity1.y < entity2.y + entity2.h &&
entity1.h + entity1.y > entity2.y) return true;
}
return false;
}
stop()
{
if (this._loop) this._loop = cancelAnimationFrame(this._loop);
}
}
class Rect
{
constructor() {
}
render(game) {
game.ctx.fillStyle = this.color;
game.ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
const PLAYER = 1, SHIP = 2, SHOT = 4, LINE = 8;
class Player extends Rect
{
constructor(px, py, pw, ph, c, v) {
super();
Object.assign(this, { type: PLAYER, rate: 0.4, delay: 2, x : px, y : py, w : pw, h : ph, color : c, vel : v });
}
update(game) {
if(keyEvent.left) {
this.x -= this.vel * game.delta;
}
if(keyEvent.right) {
this.x += this.vel * game.delta;
}
this.delay -= 0.05;
if (keyEvent.space && this.delay < 0) {
this.delay = this.rate;
game.world.add(new Shot(this.x+11, this.y-7, 7, 7, 'red', 100));
}
if (game.collide(this, PLAYER | SHIP | LINE )) game.stop();
}
}
class Ship extends Rect
{
constructor(px, py, pw, ph, c, v) {
super();
Object.assign(this, { type: SHIP, x : px, y : py, w : pw, h : ph, color : c, vel : v });
}
update(game) {
this.y += this.vel * game.delta;
if (game.collide(this, PLAYER | SHOT | LINE )) game.world.delete(this);
}
}
class Shot extends Rect
{
constructor(px, py, pw, ph, c, v) {
super();
Object.assign(this, { type: SHOT, x : px, y : py, w : pw, h : ph, color : c, vel : v });
}
update(game) {
this.y -= this.vel * game.delta;
if (game.collide(this, SHIP | SHOT | LINE )) game.world.delete(this);
}
}
class Line extends Rect
{
constructor(px, py, pw, ph, c, v) {
super();
Object.assign(this, { type: LINE, x : px, y : py, w : pw, h : ph, color : c, vel : v });
}
}
class Attack {
constructor(s) {
Object.assign(this, { size: s, rate: 0.5, delay: 0 });
}
update(game) {
this.delay -= 0.05;
if (this.delay < 0) {
this.delay = this.rate;
game.world.add(new Ship(Math.random() * 590, 5, 10, 10, 'green', 100));
if (!--this.size) game.world.delete(this);
}
}
}
const keyEvent = {
left : false,
right : false,
space : false
};
window.onkeydown = function(e) {
switch(e.keyCode) {
case 37 : keyEvent.left = true; break;
case 39 : keyEvent.right = true; break;
case 32 : keyEvent.space = true; break;
}
};
window.onkeyup = function(e) {
switch(e.keyCode) {
case 37 : keyEvent.left = false; break;
case 39 : keyEvent.right = false; break;
case 32 : keyEvent.space = false; break;
}
};
const game = new Game(document.getElementById('canvas'));
и у меня там кажется бардак в конструкторах
|
|
12.10.2017, 19:05
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
malinovsky,
this._step(0);
|
|
|
|