2016-02-18 3 views
2

Если у меня есть функция рендеринга в моей игре, например, что называется на довольно высокой скорости (определяется requestAnimationFrame), как это, например:Это хорошая идея, использовать оператор with-context с контекстом?

function render() { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 

    ctx.beginPath(); 
    ctx.arc(player.x, player.y, player.size/2, 0, Math.PI * 2); 
    ctx.fillStyle = "#6f00ff"; 
    ctx.fill(); 
} 

Почему просто не просто обернуть все это внутри с-заявление?

function render() { 
    with (ctx) { 
     clearRect(0, 0, canvas.width, canvas.height); 

     beginPath(); 
     arc(player.x, player.y, player.size/2, 0, Math.PI * 2); 
     fillStyle = "#6f00ff"; 
     fill(); 
    } 
} 

Это хорошая идея/практика? Если нет, почему бы и нет?

EDIT ///////

Для вас, ребята, которые не имеют ни малейшего представления, что HTML5 холст:

холст является ссылкой на элемент в <canvas> DOM (Document Object Model), может выглядеть как это:

var canvas = document.getElementsByTagName("canvas")[0]; 

и CTX является ссылкой:

var ctx = canvas.getContext("2d"); 

ответ

1

Это обычно не считается хорошей идеей, потому что в коде это не очевидно, если:

canvas.width = ctx.canvas.width ? 
player.x = ctx.player.x ? 

Кроме того, что если вы определили ctx как:

var ctx = { 
    clearRect: function(){/* some code */}, 
    beginPath: function(){/* some code */}, 
    arc: function(){/* some code */}, 
    fill: function(){/* some code */}, 
} 

И тогда, когда вы делаете:

with (ctx) { 
    fillStyle = "#6f00ff"; 
} 

Ожидается установка ctx.fillStyle, но это не так. Вместо этого просто задается глобальная переменная fillStyle.

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

+1

Что? Очевидно, что объект ctx является экземпляром 'CanvasRenderingContext2D', и еще более очевидно, что * не * содержит свойство игрока – super

+0

@ Murplyx - это не очевидно для всех и, возможно, не для тех, кому, возможно, придется поддерживать код. – RobG

+0

@Murplyx: Действительно ли очевидно, что объект 'CanvasRenderingContext2D' не имеет свойства' player'? Что делать, если библиотека обновлена, чтобы содержать свойство 'player', а человек, добавивший его, забыл об этом' with' statement? Именно по этой причине 'with' считается boobytrap и отключается в строгом режиме. – slebetman

1

Использование with не является хорошей идеей, на самом деле вы не должны ее использовать. Это полезно в некоторых ситуациях и у вас не один из тех, кто ограничен мало :)

На странице MDN про и против описаны:

про

Pro: Оператор with может уменьшить размер файла, уменьшив необходимость повторять длинную ссылку на объект без штрафа за производительность. Изменение цепочки областей, требуемое «с», не является дорогостоящим. Использование 'with' облегчит интерпретатор разбора повторных ссылок объектов. Обратите внимание, однако, что во многих случаях это преимущество может быть достигнуто за счет использования временной переменной для хранения ссылки на желаемый объект.

против

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

В принципе, то, что они говорят, что до тех пор, как вы используете with() конструкцию правильно, вы будете хорошо, но если вы пропустите один ключ, это будет гораздо медленнее. Шансы на это могут составлять 0%, но если в вашей программе есть ошибка - это может уловить ее и вызвать ошибку, с которой вам трудно найти при отладке.

TL; DR;

Если вы точно не знаете, что делаете, а не используете строгий режим ecmascript 5, не используйте with();, так как это скорее рискованный компромисс, чем безопасная конструкция.

Смежные вопросы