原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、写一个游戏框架(一)
5、写一个游戏框架(二)
6、通过Canvas实现视差滚动
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

在Canvas元素上实现视差滚动

http://www.brighthub.com/internet/web-development/articles/40511.aspx

视差滚动是在2D应用中创造立体纵深感的一种技术。这篇文章就来看一看在我们刚刚创建的游戏框架基础上实现视差滚动有多容易。

视差滚动

有了游戏框架,就可以通过画布元素来做一些好玩的东西了。

视差滚动指的是屏幕上的几个图层发生相对位移的效果,换句话说,背景图层滚动得比它前面的那些图层要慢一些。这种创造视觉纵深感的技术在2D游戏中的应用极为普遍。

RepeatingGameObject.js


/**
    这个类可以重复显示纹理图像,支持纹理图像在x轴或y轴偏移
    @class
*/
function RepeatingGameObject()
{
    /** 最终图像占据的宽度
 	@type Number
    */
    this.width = 0;
    /** 最终图像占据的高度
    	@type Number
    */
    this.height = 0;
    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */
    this.scrollFactor = 1;

    /**
        初始化对象
        @return 对初始化对象的引用
    */
    this.startupRepeatingGameObject = function(image, x, y, z, width, height, scrollFactor)
    {
        this.startupVisualGameObject(image, x, y, z);
        this.width = width;
        this.height = height;
        this.scrollFactor = scrollFactor;
        return this;
    }

    /**
        清理对象
    */
    this.shutdownstartupRepeatingGameObject = function()
    {
        this.shutdownVisualGameObject();
    }

	/**
        把当前元素绘制到后台缓冲
        @param dt 自上一帧绘制起经过的秒数
		@param context 绘制上下文
		@param xScroll x轴的全局滚动值
		@param yScroll y轴的全局滚动值

    */
    this.draw = function(dt, canvas, xScroll, yScroll)
    {
        var areaDrawn = [0, 0];

        for (var y = 0; y < this.height; y += areaDrawn[1])
        {
            for (var x = 0; x < this.width; x += areaDrawn[0])
            {
                // 绘制下一张贴片左上角的点
		var newPosition = [this.x + x, this.y + y];
		// 剩余的绘制空间
                var newFillArea = [this.width - x, this.height - y];
		// 第一次必须从图像的中央开始绘制
		// 后续贴片从上方或左侧绘制
                var newScrollPosition = [0, 0];
                if (x==0) newScrollPosition[0] = xScroll * this.scrollFactor;
                if (y==0) newScrollPosition[1] = yScroll * this.scrollFactor;
                areaDrawn = this.drawRepeat(canvas, newPosition, newFillArea, newScrollPosition);
            }
        }
    }

    this.drawRepeat = function(canvas, newPosition, newFillArea, newScrollPosition)
    {
        // 找到重复绘制纹理图像的起点(左上角)
        var xOffset = Math.abs(newScrollPosition[0]) % this.image.width;
        var yOffset = Math.abs(newScrollPosition[1]) % this.image.height;
        var left = newScrollPosition[0]<0?this.image.width-xOffset:xOffset;
        var top = newScrollPosition[1]<0?this.image.height-yOffset:yOffset;
        var width = newFillArea[0] < this.image.width-left?newFillArea[0]:this.image.width-left;
        var height = newFillArea[1] < this.image.height-top?newFillArea[1]:this.image.height-top;

        // 绘制图像
        canvas.drawImage(this.image, left, top, width, height, newPosition[0], newPosition[1], width, height);

        return [width, height];
    }
}
RepeatingGameObject.prototype = new VisualGameObject();

这个RepeatingGameObject类可以让图像在一个确定的区域内重复和滚动。此前,我们已经实现了绘制整幅图像。而RepeatingGameObject的不同之处在于,它拿到一幅图像并用它来填充一块范围既定的区域(其尺寸与绘制的图像无关)。我们通过这个类每次显示一幅大图像(如一座山的全景图)的一小部分,从而创建出一个背景。

也许你已经注意到了GameObjectManager的xScroll和yScroll属性,它们被传递给了GameObject的draw和updata函数。这两个值定义的是摄像机沿x轴或y轴移动了多远。RepeatingGameObject使用这两个值来它们显示的纹理,以创造移动的假象。

首先,定义RepeatingGameObject要绘制的区域。底层的GameObject类的x和y属性定义了左上角位置,而新的width和height属性定义的是绘制区域。


    /** 最终图像占据的宽度
 	@type Number
    */
    this.width = 0;
    /** 最终图像占据的高度
    	@type Number
    */
    this.height = 0;
    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */

而scrollFactor属性用于改变RepeatingGameObject滚动的量,该变化是通过传递到draw函数的xScroll和yScroll来控制的。将scrollFactor设置为小于1的值,会导致滚动变慢,从而造就画面中的远景。


    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */
    this.scrollFactor = 1;

最后两个draw和drawRepeat函数具体负责渲染贴片及偏移的纹理。


	/**
        把当前元素绘制到后台缓冲
        @param dt 自上一帧绘制起经过的秒数
		@param context 绘制上下文
		@param xScroll x轴的全局滚动值
		@param yScroll y轴的全局滚动值

    */
    this.draw = function(dt, canvas, xScroll, yScroll)
    {
        var areaDrawn = [0, 0];

        for (var y = 0; y < this.height; y += areaDrawn[1])
        {
            for (var x = 0; x < this.width; x += areaDrawn[0])
            {
                // 绘制下一张贴片左上角的点
		var newPosition = [this.x + x, this.y + y];
		// 剩余的绘制空间
                var newFillArea = [this.width - x, this.height - y];
		// 第一次必须从图像的中央开始绘制
		// 后续贴片从上方或左侧绘制
                var newScrollPosition = [0, 0];
                if (x==0) newScrollPosition[0] = xScroll * this.scrollFactor;
                if (y==0) newScrollPosition[1] = yScroll * this.scrollFactor;
                areaDrawn = this.drawRepeat(canvas, newPosition, newFillArea, newScrollPosition);
            }
        }
    }

    this.drawRepeat = function(canvas, newPosition, newFillArea, newScrollPosition)
    {
        // 找到重复绘制纹理图像的起点(左上角)
        var xOffset = Math.abs(newScrollPosition[0]) % this.image.width;
        var yOffset = Math.abs(newScrollPosition[1]) % this.image.height;
        var left = newScrollPosition[0]<0?this.image.width-xOffset:xOffset;
        var top = newScrollPosition[1]<0?this.image.height-yOffset:yOffset;
        var width = newFillArea[0] < this.image.width-left?newFillArea[0]:this.image.width-left;
        var height = newFillArea[1] < this.image.height-top?newFillArea[1]:this.image.height-top;

        // 绘制图像
        canvas.drawImage(this.image, left, top, width, height, newPosition[0], newPosition[1], width, height);

        return [width, height];
    }   

ApplicationManager.js


/**
    ApplicationManager用于管理应用
    @class
*/
function ApplicationManager()
{
    /**
        初始化对象
        @return A 对初始化对象的引用
    */
    this.startupApplicationManager = function()
    {
        this.startupGameObject();
	this.background3 = new RepeatingGameObject().startupRepeatingGameObject(g_back2, 0, 100, 3, 600, 320, 1);
        this.background2 = new RepeatingGameObject().startupRepeatingGameObject(g_back1, 0, 100, 2, 600, 320, 0.75);
        this.background = new RepeatingGameObject().startupRepeatingGameObject(g_back0, 0, 0, 1, 600, 320, 0.5);
        return this;
    }

	/**
        更新当前对象
        @param dt 自上一帧绘制起经过的秒数
        @param context 绘制上下文
        @param xScroll x轴的全局滚动值
        @param yScroll y轴的全局滚动值
    */
    this.update = function(/**Number*/ dt, /**CanvasRenderingContext2D*/ context, /**Number*/ xScroll, /**Number*/ yScroll)
    {
		g_GameObjectManager.xScroll += 50 * dt;
	}
}
ApplicationManager.prototype = new GameObject

在这里,我们通过ApplicationManager创建了三个RepeatingGameObject类的实例,每个实例分别显示为一个图层,使用z(深度)和scrollFactor值来创造RepeatingGameObject 渐远和渐慢的效果。

最终结果很不错。视差滚动为画布赋予了完美的纵深感,而整个效果只多编写了一个类就实现了。

看一看视差滚动的Demo吧。http://webdemos.sourceforge.net/jsplatformer4/jsplatformer4.html

原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、写一个游戏框架(一)
5、写一个游戏框架(二)
6、通过Canvas实现视差滚动
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

4、写一个游戏框架(二)

在这篇文章里,我们继续介绍构成这个基本JavaScript游戏框架的其他必要的类。

前一篇文章介绍了GameObjectManager类,该类负责画布的渲染并允许GameObject类更新和删除它们自己。下面就来看一看GameObject类。

GameObject.js


/**
    游戏中出现的所有元素的基类
    @class
*/
function GameObject()
{
    /** 显示的深度次序。较小的zOrder值表示先渲染,因而会在背景中。
        @type Number
    */
    this.zOrder = 0;
    /**
        x轴的坐标
        @type Number
    */
    this.x = 0;
    /**
        y轴的坐标
        @type Number
    */
    this.y = 0;

    /**
        初始化游戏对象,并将其添加到GameObjectManager维护的对象列表中
        @param x        x轴的坐标
        @param y        y轴的坐标
        @param z        元素的z次序(背景元素的z值较小)
    */
    this.startupGameObject = function(/**Number*/ x, /**Number*/ y, /**Number*/ z)
    {
        this.zOrder = z;
        this.x = x;
        this.y = y;
        g_GameObjectManager.addGameObject(this);
        return this;
    }

    /**
        清理当前对象,将其从GameObjectManager维护的对象列表中删除
    */
    this.shutdownGameObject = function()
    {
        g_GameObjectManager.removeGameObject(this);
    }
}

这个GameObject类(是一个引擎类)的目的,是为游戏中将会出现的所有对象定义一些共有的属性,包括它们的位置(x和y)和深度(z)。需要注意的是,我们不会直接创建GameObject类的实例,而是会再创建一个类来扩展它。

这个类的x和y坐标值没有什么好说的——就是相应对象左上角位置在画布上的坐标。关键是GameObject中的z值,这个值定义的是对象的深度。理解这个值很重要,这个值较小的GameObject会先绘制到画布上。换句话说,z值较大的GameObject将被绘制到z值较小的GameObject上面。
查看全文 »

原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、写一个游戏框架(一)
5、写一个游戏框架(二)
6、通过Canvas实现视差滚动
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

4、写一个游戏框架(一)

http://www.brighthub.com/internet/web-development/articles/40512.aspx
在知道了如何使用画布元素之后,接下来我教大家写一个框架,有了这个框架,我们就可以把它作为基础来创建游戏。在这第一部分,我们会介绍前两个文件/类。

编写代码之前,我们先来看一看随后几篇文章将致力于创建的示例Demo。表面上看起来,这个Demo跟第二篇文章里的那个没啥区别,但如果你看看后台(查看网页源代码)就会发现,为了更方便地创建这个最终效果,一个凝聚不少心血的基础框架已经写好了。

下面我们要介绍的JavaScript代码使用面向对象的方式来编写。对于没有编写过多少JavaScript代码的人来说,恐怕第一眼看到它们会觉得有点奇怪。如果你真的不太熟悉JavaScript的面向对象编程,建议通过Mozilla Developer Network的这个教程https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript来补补课。这篇教程里解释了我们稍后会用到的一些编程技术。

从设计思想上来看,这个框架可以分成两部分:与底层的2D引擎交互的类(用于操作画布、控制渲染循环、处理输入等的代码)和用来创建对象以便构成游戏的类。前者可以归为引擎类,后者可以归为应用类。由于应用类要构建于引擎类之上,所以我们需要先来创建引擎类。
查看全文 »

原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、通过Canvas实现视差滚动
5、写一个游戏框架(一)
6、写一个游戏框架(二)
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

3、通过Canvas元素实现高级图像操作

http://www.brighthub.com/internet/web-development/articles/39509.aspx

这篇文章将带领大家学习使用JavaScript和Canvas元素操作图像了几种不同的方式,这些方式在Canvas元素出现之前是不可能的事儿。

上一篇文章演示了如何利用Canvas实现一个基本的图像动画。那个例子很简单,同样的效果通过修改IMG或DIV等标准HTML元素的一些属性,照样也可以轻易实现。下面我们就来演示一下画布元素的高级应用,展示一下它的真正威力。

首先,还是准备一个HTML页面。


  < !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
  <html lang="en">
     <head>
        <title>JavaScript Platformer 2</title>
        <script type="text/javascript" src="jsplatformer2.js"></script>
        <style type="text/css">
           body { font-family: Arial,Helvetica,sans-serif;}
        </style>
     </head>
    <body>
       <p>
          <a href="http://www.brighthub.com/internet/web-development/articles/38364.aspx">
             Game Development with Javascript and the canvas element
          </a>
       </p>
       <canvas id="canvas" width="600" height="400">
          <p>Your browser does not support the canvas element.</p>
       </canvas>
       <br />
       <button onclick="currentFunction=alpha;">Change Alpha</button>
       <button onclick="currentFunction=shear;">Shear</button>
       <button onclick="currentFunction=scale;">Scale</button>
       <button onclick="currentFunction=rotate;">Rotate</button>
    </body>
 </html>

与上个一例子的HTML页面相比,唯一的区别就是添加了一些按钮。单击这些按钮,就会设置currentFunction变量(稍后介绍)的值,用以改变在渲染循环中运行的函数。
查看全文 »

原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、通过Canvas实现视差滚动
5、写一个游戏框架(一)
6、写一个游戏框架(二)
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

1、认识一下Canvas

http://www.brighthub.com/internet/web-development/articles/38364.aspx

Canvas元素以及JavaScript引擎中新增的一些特性,让Web开发人员不必借助第三方插件,即可设计开发出精细且具有交互性的2D网页。这篇文章就向大家介绍一下Canvas元素,以及它的一些可能的用途。

JavaScript与Canvas元素

HTML是为创建静态页面而生的。HTML所能实现的动态效果,也仅限于显示GIF动画和闪烁的文本。JavaScript改变了这一切,通过它能够动态修改网页。今天,很多Web服务都利用AJAX来创建网页,为用户提供更加流畅的体验,也超越了标准HTML页面中常见的“点击-重新加载-点击”式的交互模式。

然而,JavaScript的某些功能会受到其宿主浏览器的制约。尽管可以在网页中创建和修改任何元素,但JavaScript不能(轻易地)让浏览器显示一种新对象。通过JavaScript修改文本、插入图像或者缩放表格都很容易,因为这些对象本来就是HTML所支持的。如果你想再玩得刺激一点,比如写一个网页游戏,怎么办?那恐怕就得苦心积虑地改变标准HTML元素的用途,克服种种不测才能达到目的。要么,你就得求助于Flash或Silverlight这样的插件。

Canvas元素登场了。这个新HTML元素为JavaScript开发者提供了一种无需插件即可在网页中直接绘图的机制。Canvas元素最早是由苹果公司在其WebKit框架中引入的,Safari浏览器和Dashboard微件都在使用。Canvas元素现在也被建议加入了HTML5规范,得到了最新的Chrome、Firefox、Opera以及Konqueror等浏览器的支持。Internet Explorer(至少在IE8之前)还不支持Canvas,但ExplorerCanvas项目倒是为IE提供了与Canvas元素类似的功能。

Canvas元素对做过2D图形编程的人是小菜一碟。可以在这个元素上画线、画各种形状、画渐变,甚至可以利用与其他2D API中类似的函数来修改其中的每一个像素。得益于Chrome的V8、Firefox的SpiderMonkey以及Safari的Nitro等最新JavaScript引擎的性能,创建精细且具有交互性的Web应用已经完全没有问题。

我们这一系列文章将教会大家使用JavaScript和Canvas元素创建一个简单的平台游戏。将要涉及的内容包括动画、加载资源、分层渲染、滚动和交互。通过一步一步地展示示例代码和实际效果,你可以很快学会如何驾驭强大的Canvas元素。

2、在Canvas上绘图

http://www.brighthub.com/internet/web-development/articles/38744.aspx

下面,我们就通过一个循序渐进的示例及实时演示,来介绍如何使用JavaScript在Canvas元素上绘图及实现动画。

准备工作

知道了什么是Canvas元素之后,该学习在屏幕上绘图了。首先,需要一个HTML页面来放置和显示Canvas元素。
查看全文 »

原文地址:http://martinfowler.com/bliki/SoftwarePatent.html

在软件开发领域中,几乎所有我认识的人都对专利以及我们利用它的方式深恶痛绝。很长时间以来,我一直准备写篇文章,谈谈专利这玩艺儿,但一直迟迟没有动笔。最近,在收听了This American Life制作的一期特别棒的新闻观察节目(http://www.thisamericanlife.org/radio-archives/episode/441/when-patents-attack)之后,才决定把这篇文章写出来。我这篇文章的大致意思就是,虽然专利(包括软件专利)从原理上讲是个不错的想法,但在实践当中,各种专利已经给我们带来了无法容忍的灾难,取消这玩艺儿才是上策。

不过,首先还是来看一看为什么我说专利从原理上讲是个不错的主意,而且堪称人类历史上一个最有价值的“发明”。

关于专利在人类发展史中扮演的这个重要角色,Willian Rosen在他的书 The Most Powerful Idea in the World 中给出了很好的论述。Rosen在这本书里回顾了工业革命,而且他把工业革命刻画成了人类历史中最重要的事件,一个使人类财富得以向前迈进了一步的事件。

在17世纪的英格兰、法国,甚至中国,一名熟练的体力劳动者(比如纺织工或铁匠),每周工作的小时数大致相同,生产的布和钉子的数量也大致相同,而且跟他们奥古斯都时代(公元前63年至公元前14年。——译者注)的远祖也没有多大差别。他们能挣到相同数量的货币,能买到相同数量和种类的食物。他们的妻子,同样跟她的远祖一样,忙着准备一日三餐;她们也许会从本村面包师傅那儿买点面包,但除此之外,差不多什么都是自己亲自动手加工。她们甚至还要给全家人做衣服,天气变幻无常,衣服的样式也不尽相同。而且,这在很大程度上也让人无法把当时的家庭与10个世纪前的家庭区分开来,差不多清一色的自织土布,产麻区也会用亚麻布来做衣服。这样的劳动者和他的妻子,一般会生育八到十个后代,但能活到成年的差不多只有三个。如果这个劳动者要出门,那他只有靠步行;当然,如果他们家日子特别富裕的话,会花钱雇一辆两轮或四轮的马车。步行的话,每小时走三英里,坐马车则每小时走七英里。当然,时速跟他们的祖先也一样。而这就意味着,他的世界也就是他出生的地方加上方圆五、六英里远的范围这么大。

之后,历史上第一次,一切都发生了变化。这些劳动者的境况发生了最根本的变化。14世纪君士坦丁堡的一名熟练织工,只要工作三个小时就可以挣够买一磅面包的钱。到1800年,诺丁汉的一位织工为此则至少要工作两个小时。但到了1900年,买这块面包只要工作不到15分钟就够了。而到2000年,只要5分钟。这个已经是老生常谈的事实告诉我们,在发达的21世纪,一个中产阶级家庭所能享受到的奢华生活,在两个世纪以前,是连国王都很难承受得起的。

——William Rosen

查看全文 »

原文地址:http://ebm.e.borders.com/c/tag/hBOKNiQAQfEXsB8cdgOAESqwkGW/doc.html

新爱的Borders Rewards会员,

相信你们已经听说了,Borders在经过40多年为几代读者点燃热爱阅读的薪火之后,将要全面关门停业了。宣布这个消息,我们也感到非常抱歉,因为在我们奋力拯救公司之际,你们始终与我们站在一起。我想以个人名义向你们表示感谢,感谢你们的忠实与支持,无论你是180万Borders Rewards Plus计划的注册会员之一,还是曾在我们的商店或Borders.com上买过东西,或者花时间通过邮件或电话方式向Borders表示过支持。

你可能会想,发生了什么事?Borders怎么就经营不下去了呢?简单地说,相关各方经过反复协商,也都尽了最大努力,没有出价人正式提议我们公司继续经营。因此,根据我们的债务持有人融资协议,我们向法院递交了申请,请求批准其他公司购买我们商店的资产,并执行清算程序。

为了避免这个结果发生,我们已经尽了很大努力。但事实上,很长时间以来,Borders一直面对不利的市场形势,包括图书业的迅速变化、电子阅读器的革命,以及动荡的经济。我们也曾奋力一搏,绝地反击,但令人遗憾的是,我们最终没有战胜这些外来的力量。

所有门店将于7月22日星期五开始停业甩卖。希望大家利用这次绝无仅有的机会,以意想不到的折扣买到自己心仪的图书或其他商品。清算销售期间,礼品卡可以继续使用,Borders Rewards Plus会员到8月5日之前仍将享受其会员折扣。此外,全部Borders Bucks在7月31日前仍然可以使用,过期作废。

几十年来,Borders商店一直是读者寻求知识、快乐和灵感,以及与那些充满激情的人交流思想的地方。我很荣幸,能够有机会领导Borders并在扩大阅读范围和传播阅读兴趣的伟大事业中扮演了一个角色。作为一家公司,对于你们能接受我们的服务,对于另外几百万客户数年来从我们商店购物,我们感激不尽。我衷心希望Borders永远活在读者的心中。

非常感谢,

Mike Edwards
Borders公司CEO

原文地址:JavaScript is Assembly Language for the Web: Part 2 – Madness or just Insanity?

有些人认为“JavaScript是Web的汇编语言”完全是精神病说的话。为此,我询问了几位JavaScript权威,比如Brendan Eich(JavaScript之父)、Douglas Crockford(JSON之父),还有Mike Shaver(Mozilla技术副总裁)。以下都是从个人邮件里摘过来的,得到了以上几位的许可。

Mike Shaver

以前我就听说过这种比较,我认为很大程度上确实如此。但是,这种说法忽视了JS开发人员与机器之间的人机工程学方面的大量努力,因为汇编语法设计得没有那么人性化(特别是现代的汇编语言)。

Brendan Eich

几年前,我曾说过“JS是Web的x86”(好像是在一次JSConf上),不过我不敢说我是第一个这么说的。(Nick Thompson今年也在Hacker News中这么说过。)

关键在于,JS确实在按照我们想的,越来越往低级方向发展了。但它也具备高级的特性。

Shaver说得没错,汇编缺少可靠的宏处理器,因此不适合程序员,也不够安全。但JS可不是这样。所以,这个比喻需要加点限制条件,不然就要闹出笑话来了。

无论从高级函数式编程还是内存安全角这个角度看,还是从低级特性,像类型化数组以及即将成为现实的ES中类型化数组的扩展、二进制数据,等等来说,JS都是一个比汇编更加强大的编程语言。当然了,内存安全是首要的区别。

查看全文 »

原文地址:JavaScript is Assembly Language for the Web: Sematic Markup is Dead! Clean vs. Machine-coded HTML

(更新)有些人认为“JavaScript是Web的汇编语言”完全是精神病说的话。为此,我询问了几位JavaScript权威,比如Brendan Eich(JavaScript之父)、Douglas Crockford(JSON之父),还有Mike Shaver(Mozilla技术副总裁)。他们的评论发表在下一篇文章里

昨天我跟Erik Meijer聊天,他说:

JavaScript就是一个汇编语言。JavaScript加上生成的HTML就像是.NET汇编一样。浏览器可以执行这些代码,但没人真的关心里面到底写的是什么。
——Erik Meijer

怎么会说起这件事儿呢?当时我正在试用Google+,就跟上大多数让我印象深刻的网站一样,我立即就查看它的源代码。不看不要紧,一看吓一跳:

咱就将就说吧,我看到了1300行代码,密密麻麻的,大约90KB。上面图片显示的只是最前面的一小部分,基本上都是“瘦身后”的JavaScript代码。再往下看,页面中间呢,全都是像下面这样的span、div以及生成的类和id: 查看全文 »

日文版:Mr Junichi Niino,Rubyの進歩がより速くなることを期待している
英文版:I am looking forward to accelerating Ruby’s progress

我在前一篇文章里已经提到过了,松本行弘(Yukihiro Matsumoto,或Matz)已经加入了Heroku,成为该公司的首席Ruby架构师。我通过电子邮件询问了Matz对自己未来的设想。

“让Ruby核心功能更丰富、品质更高是我的使命。”

PublicKey(以下称Q):能不能介绍一下你怎么就换工作了呢?

松本行弘先生(以下称Matz):上一次跟Marc Benioff先生(Salesforce.com的CEO)碰面时,他就问我,怎么才可以支持Ruby的开发。

于是,我就说了,我说我想要改变当前大多数Ruby核心开发人员面临的窘境:这些人有的是牺牲自己的闲暇时间来完成自己的工作,有的还在为自己的职业前途担心。

然后,他就说他可以为我们提供一些支持,而这也是我通过Heroku加入Salesforce.com的原因(注意:目前还有几位Ruby核心开发人员也正协商加入Heroku)。

也就是说,我们工作的核心内容没有变。我们的使命依旧还是开发Ruby核心,把它变得功能更丰富、品质更高。如此说来,我期待着我们提供的职业前景,以及来自包括Heroku在内的大量Ruby用户的反馈,能够加速Ruby开发的进程。要不然,我换这次工作就没有什么意义了。

不过,加入Heroku并担任他们的首席架构师,并不意味着我只关心Heroku和Salesforce.com的发展。我加入他们不会改变我与NaCI还有Rakuten的合作关系,后两者仍然会继续支持我,而且我还将继续担任Ruby协会的会长一职。

我为什么选这个头衔?因为我觉得“首席架构师”这个名字听起来显得最容易与业务撇清关系。我不打算将来在Heroku参与任何业务上的决策。

Q:你对自己在Heroku的角色有什么期许?

Matz:刚才不是已经说了嘛,我的工作没有什么变化,但我们的开发进度会加快。除此之外,我还能与Heroku进行更加密切的沟通,以便尽早解除Ruby对云计算平台的限制(如果有限制的话)。

而且,我还会继续与Engine Yard、VMWare等公司保持良好的关系,即使我加入了Heroku,我仍然还是那个“Ruby的Matz”,不会辜负他们的信任。

Q:此时此刻,你对Ruby和云计算有什么看法?

Matz:说实话,很多Ruby核心开发人员(包括我自己)都对Web没有多大的兴趣,但云计算会变得越来越重要,这一点是显而易见的。所以,我希望能从这些云计算运营商那里得到更多的需求,以便将其反映到未来的Ruby中。

Q:你会去硅谷上班吗,还是在松江远程工作?

Matz:我的生活方式不会变(但工作方式会变),所以多数时候我会在松江的家里远程参与开发。

就我自己而言,搬到硅谷去工作不一定会比现在这个环境更好。

不过,我想我每年都会跟旧金山/硅谷(包括Heroku)的那些人直接沟通几次。

(注意:大家别误会,Heroku的总部在旧金山,不在硅谷,但他们在新闻稿里自称是“硅谷公司”。)

Q:还有别的要说的吗?

Matz:我听说很多(日本之外国家的)人并不知道,Ruby核心团队迄今还没有一个可持续的发展模式。我希望我这次换工作能为代表日本发布消息的日本软件开发人员树立一个榜样。

Q:谢谢你接受采访。