小兔子的画法
39
function getOffset (x, y, w, h, placement) {
var offset
switch (placement) {
case 'bottom':
offset = {
top: y + h,
left: x + w/2
}
break
case 'top':
offset = {
top: y,
left: x + w/2
}
break
case 'left':
offset = {
top: y + h/2,
left: x
}
break
case 'right':
offset = {
top: y + h/2,
left: x + w
}
break
}
return offset
}
Notice the difference between this function and the following function, not in terms of
computing performance (where the difference is inconsequential), but rather in pure
cognitive pacing. The next function returns the same result, but with a quicker, more
succinct rhythm (return > this/that, this/that, this/that):
function getOffset (x, y, w, h, placement) {
return placement == 'bottom' ? { top: y + h, left: x + w/2 } :
placement == 'top' ? { top: y, left: x + w/2 } :
placement == 'left' ? { top: y + h/2, left: x } :
{ top: y + h/2, left: x + w }
}
A third function might even exaggerate the pacing further, focusing in on the return
object itself—clearly calling out expected properties “top” and “left”—but with a more
complex rhythm, forking the conditions at the object’s properties:
function getOffset (x, y, w, h, placement) {
return {
top : placement == 'bottom' ? y + h :
placement == 'top' ? y : y + h/2,
left : placement == 'right' ? x + w :
WHAT DOES THIS HAVE TO DO WITH JAVASCRIPT?
31
placement == 'left' ? x : x + w/2
}
}
As you’ve begun to see, expressions guide our reading of software. In JavaScript, the
potential for this sort of variation both enables and is enabled by experimentation and
play—which therefore should be championed and not discouraged.
With So Much Variation, Which Way Is Correct?
Imagine sitting several adults down in a room and providing them with an actual
image of a rabbit and adequate drawing supplies. Imagine asking them each to draw a
rabbit.
Depending on the group’s exposure to various drawing techniques, you’d likely
receive a variety of renderings, ranging from rather crude to rather capable.
Variety here becomes a metric for the lack of experience in drawing amongst the
group. Which is to say, if everyone were perfect at illustration they would each have
rendered a photorealistic image, indistinguishable from the image of the rabbit; there
wouldn’t have been any variety at all.
This is because to draw a rabbit is to exercise one’s ability to duplicate. It is an exercise
in experience and mimicry. There is a right answer, and thus, there isn’t room for
creativity.
But what if you had asked the same group to draw a bunny?
Arguably the request is at once less threatening, less rigid, and less scientific. To draw a
bunny is to draw a rabbit-like thing. It is exceedingly difficult to be critical of a bunny
drawing because at most it’s only ever a resemblance.
Following this, you could expect the variety in the group’s images to be even more
exaggerated. To draw a bunny is to celebrate and to lean on variety. Here, however, vari-
ety no longer takes a negative form. Instead, it is symptomatic of the potential for creative
expression implicit in the act of drawing without bounds. It is a positive metric for
inventiveness and imagination.
To draw a bunny is to engage with variety. It serves to challenge the image of the rab-
bit by introducing new means of achieving likeness.
Consider immediately invoked function expressions (IIFEs). By convention, an IIFE
takes one of the two following forms:
(function (){})()
(function (){}())
CHAPTER THREE: HOW TO DRAW A BUNNY
32
你已逐渐意识到,表达方式对我们阅读软件代码能起到引导作用。
JavaScript
支持以
多种表达方式实现同一功能,这种变化多端的潜力既适合实验,也适合把玩,因而
我们应予以拥护而不是贬斥。
表达形式多样,哪种正确?
想象有如下场景,请几位成年人坐到一间屋子里,向其展示一张兔子的真实照片,
并提供齐全的绘画材料。请每人画一幅兔子。
由于他们接触绘画技艺的程度不一而同,因此很可能你收上来的画作水平参差不齐,
有的粗糙,有的技艺不凡。
多样性成为衡量大家绘画经验欠缺程度的一把尺子。换句话说,如果人人擅长绘画,
那么每个人的作品应像照片一样逼真,与兔子的照片放在一起,应该难以区分;也
就是大家不会对兔子原本的形象做任何改动。
这是因为画兔子是要练习一个人的复制、感知和模仿能力。因此正确答案是唯一的,
并未赋予他们发挥创意的余地。
你刚才若是要求他们画小兔子又会怎样?
可以说,该要求一出,他们立刻觉得自由发挥的空间较大,对严格、精确地再现照
片要求不高。画小兔子是指画类似兔子的东西。评判小兔子画的如何极其困难,因
为顶多只是要求有几分像兔子即可。
你要求他们画小兔子,收上来的作品与要求画兔子时交上来的作品不同,作品千姿
百态。画小兔子就是要拥抱多样性,依靠多样性。注意,这儿的多样性不再表示大
家水平参差不齐的程度,也不再有否定意味。相反,它象征着在不受限制的前提下
自由发挥的潜力有多大,因此可用来衡量创造力和想象力的大小。
画小兔子要去尝试多种多样的方法,用新方法来画兔子,与兔子原本的形象保持几
分相似即可,同时要对原有形象发出挑战。
我们以立即执行函数表达式
IIFE
作为例子。按照惯例,
IIFE
不外乎以下两种形式
(function (){})()
(function (){}())
如果要画小兔子,我们要打破传统,而不是遵循传统,积极使用不同的表达方式
一种表达方式不会绝对地优于另一种。带着这种认识,我们来看下面这些
IIFE
的写
法:
!function (){}()
~function (){}()
+function (){}()
-function (){}()
new function (){}
1,function (){}()
1&&function (){}()
var i=function (){}()
以上每种写法均有独到的优势,有的字节数更少,有的对于拼接操作更安全。这些
写法都是合法、可执行的
JavaScript
语句。
对课堂教学有怎样的影响?
学校所能安排的年级就那么多,因此我们在校读书的时间很有限,学校遂用大部分
时间教我们画兔子。

Get JavaScript 之美 now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.