美高梅官方网站66159

而Dart的存在似乎正是为了弥补JavaScript的这些,按HTML文档流顺序执行JavaScript代码

作者:美高梅官方网站66159    来源:未知    发布时间:2020-05-08 06:22    浏览量:

在谷歌工程师拉尔斯·巴克(Lars Bak)的V8 JavaScript解释器颠覆了Firefox所宣称的速度这一背景之下,我们有理由相信,谷歌新的网络开发语言很可能与Smalltalk类似。但是 这可能会引领网络走向一个截然不同的方向。在今天丹麦举行的网络开发者大会上,谷歌和Chromium开源开发团队的成员揭开了谷歌寄予厚望的新的、更为 结构化的网络编程方法——Dart的神秘面纱。Dart的正常运行需要一个新的虚拟机,这就使得Dart处于与Java、Adobe Flash以及Microsoft、Silverlight竞争的地位。但是从结构上说,至少是现在,Dart将会更依赖于浏览器。

之前从JavaScript引擎的解析机制来探索JavaScript的工作原理,下面我们以更形象的示例来说明JavaScript代码在页面中的执行顺序。如果说,JavaScript引擎的工作机制比较深奥是因为它属于底层行为,那么JavaScript代码执行顺序就比较形象了,因为我们可以直观感觉到这种执行顺序,当然JavaScript代码的执行顺序是比较复杂的,所以在深入JavaScript语言之前也有必要对其进行剖析。1.1 按HTML文档流顺序执行JavaScript代码首先,读者应该清楚,HTML文档在浏览器中的解析过程是这样的:浏览器是按着文档流从上到下逐步解析页面结构和信息的。JavaScript代码作为嵌入的脚本应该也算做HTML文档的组成部分,所以JavaScript代码在装载时的执行顺序也是根据脚本标签

图片 1

如果通过脚本标签

 谷歌计划使Dart虚拟机作为浏览器现在使用的JavaScript引擎的补充。也就是说,它可以把Dart代码转变 成JavaScript代码。谷歌尽量去回避关于Dart被嵌入所有的浏览器的可能性,不过在今天早上发表的一篇博文里,拉尔斯·巴克提及关于将Dart 虚拟机整合到谷歌浏览器的问题,并明确表示:“我们将计划去探索这个项目。” 

alert;

终于有了类

1.2 预编译与执行顺序的关系

 与C#和java等更加结构化、面向对象的语言相比,JavaScript往往会有很多累 赘;与Python、Ruby以及D等更加智能化的动态语言相比,JavaScript又显得比较冗长,无法快速地切入主题。因此随着时间的推 移,JavaScript在“开放式网络”的分布式应用程序功能上的统治地位似乎有所动摇。而Dart的存在似乎正是为了弥补JavaScript的这些 不足。

在Javascript中,function才是Javascript的第一型。当我们写下一段函数时,其实不过是建立了一个function类型的实体。 就像我们可以写成这样的形式一样:复制代码 代码如下:functionHello; }Hello(); varHello = function;} Hello(); 其实都是一样的。 但是当我们对其中的函数进行修改时,会发现很奇怪的问题。复制代码 代码如下: functionHello; } Hello { alert; } Hello(); 我们会看到这样的结果:连续输出了两次Hello World。而非我们想象中的Hello和Hello World。 这是因为Javascript并非完全的按顺序解释执行,而是在解释之前会对Javascript进行一次“预编译”,在预编译的过程中,会把定义式的函数优先执行,也会把所有var变量创建,默认值为undefined,以提高程序的执行效率。也就是说上面的一段代码其实被JS引擎预编译为这样的形式:复制代码 代码如下: varHello = function; } Hello = function() { alert; } Hello; 我们可以通过上面的代码很清晰地看到,其实函数也是数据,也是变量,我们也可以对“函数“进行赋值。当然,我们为了防止这样的情况,也可以这样:复制代码 代码如下: functionHello; } Hello(); functionHello() { alert; } Hello(); 这样,程序被分成了两段,JS引擎也就不会把他们放到一起了。

随着第一部Dart教程的问世,拉尔斯·巴克和他的开发团队从JavaScript的基础做起,加入了一些关键的java元素并提高了解释器的潜在假设能力来使其变得更为简洁。另外非常关键的补充就是使用了真正的类结构以及java开发人员所熟悉的类关键字。

当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。

JavaScript中有一些使用关键 字函数的方法来使其偏向于面向对象。例如,我们可以声明一个恰好具有属性的函数,并且它的功能是作为一种方法嵌入其中,但问题是方法本身并不会得到重载而 是每次都要重新创建,所以就要把方法作为一种附加方式添加到函数原型。或者,我们可以声明一个使用通用实例的对象,它可能要用常量来定义内部结构,然后我 们可以选择一个常量来为这个函数赋值,以使其具备变量的特征。或者我们可以假定该函数是对象的唯一组成部分,然后声明一个变量,把函数值赋给它。

做如下处理:

但是这些方法并不够完美。许多由最新一代的JavaScript引擎例如V8和Mozilla的TraceMonkey等执行的任务,事实上就是把压缩了的繁琐的“垃圾代码”转变成相对简洁精确的代码。

1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。

所以从理论上说,由浏览器运行Dart虚拟机所导致的性能下降问题可以在代码方面得到补偿,因为这些代码对于JavaScript解释器来说更容易分析。但这仅仅是理论上。

2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined) 所以,就会出现当JavaScript解释器执行下面脚本时不会报错:

Dart以一种大多数java程序员所熟悉的方式再次引入了类。并且其中的一些调整使得定义更加简洁;例如自反指示符this会被用在声明用户方法的 内部(例如用Ball.throw(this.distance);而不用Ball.throw(distance); this.distance = distance;)。同时接口也支持创建用户属性和多个类的公用方法;还有如人们所期待的那样一个类实现一个接口。

复制代码 代码如下:alert; // 返回值undefined

仍是未知:事件的触发 

var a =1;

有些JavaScript开发者反对的一个显著的结构变化是关系到上下文。JavaScript函数往往是粘贴在整个页面上的,尽管其中有些地方它 应该是一个main()函数,但是大多数函数是由浏览器事件触发的,包括window.onload。在Dart中,每一个<script> 元素都是一个自包含的上下文。类成员和变量被默认为是公有的(在Dart中没有“public”这个关键字),尽管对于Dart来说“public” 仅仅是脚本,而并非一个涵盖整个页面的作用域。

alert; // 返回值1由于变量声明是在预编译期被处理的,所以在执行期间对于所有代码来说,都是可见的。但是,你也会看到,执行上面代码,提示的值是undefined,而不是1。这是因为,变量初始化过程发生在执行期,而不是预编译期。在执行期,JavaScript解释器是按着代码先后顺序进行解析的,如果在前面代码行中没有为变量赋值,则JavaScript解释器会使用默认值undefined。由于在第二行中为变量a赋值了,所以在第三行代码中会提示变量a的值为1,而不是undefined。

“在JavaScript中,跨多个脚本标签的声明在同一个命名空间里被组合在一起,”Sigmund Cherem 和Vijay Menon在今天早上写道,“在Dart中,在一个脚本标签中的代码无法直接访问定义在另一个中的代码。如果一个脚本希望从另一个不同的URL加载代码, 那么它必须通过#import来导入。每个脚本标签必须定义自己的main()入口才能运行。

同理,下面示例在函数声明前调用函数也是合法的,并能够被正确解析,所以返回值为1。

main()函数是DOMContentLoaded事件的事件处理程序。否则,我们不会从早期文档编制中看到任何关于Dart代码如何以 JavaScript代码的方式回应浏览器事件的迹象。如果Dart没有做出任何改变的话,那么我们可以预见,在DOM加载前什么都不会运 行,main()函数也就可以写为空的,而其它函数对事件做出响应——这和JavaScript所产生的情况一样糟糕。

复制代码 代码如下:f(); // 调用函数,返回值1

但是可以想象,这个方案将会使多线程处理变得异常简单和直接:一个页面可以有多个脚本,而且虚拟机可以并行运行它们……再次强调,这仅仅是根据早期 文档编制,从理论上来讲。目前浏览器尚未具备多线程解释器,Dart也并没有强大到包括JavaScript虚拟机,因此很难想像Dart将如何调用一个 事实上并不存在的功能。

function f;

然而,从结构的角度来讲,关于Dart还有很多是值得期待的,并且我们有理由相信它将会支持甚至包括Internet Explorer在内的诸多浏览器。因此Dart将会如何冲击浏览器的HTML5应用程序(或者说是“本机应用程序”)仍有待观察。我们这周将密切关注来 自开发者大会及谷歌的消息。

}

英文文章:原文链接

但是,如果按下面方式定义函数,则JavaScript解释器会提示语法错误。

文章转载自:开源中国社区 [http://www.oschina.net]

复制代码 代码如下:f(); // 调用函数,返回语法错误

var f = function;

}

这是因为,上面示例中定义的函数仅作为值赋值给变量f,所以在预编译期,JavaScript解释器只能够为声明变量f进行处理,而对于变量f的值,只能等到执行期时按顺序进行赋值,自然就会出现语法错误,提示找不到对象f。

再见一些例子:

复制代码 代码如下:

/*在预编译过程中func是window环境下的活动对象中的一个属性,值是一个函数,覆盖了undefined值*/

alert; //function func}

var func = "this is a variable"

function func(){

alert

}

/*在执行过程中遇到了var重新赋值为"this is a variable"*/

alert; //this is a variable

复制代码 代码如下:

虽然变量和函数声明可以在文档任意位置,但是良好的习惯应该是在所有JavaScript代码之前声明全局变量和函数,并对变量进行初始化赋值。在函数内部也是先声明变量,然后再引用。

1.3 按块执行JavaScript代码

所谓代码块就是使用

// JavaScript代码块2

function f;

}

JavaScript解释器在执行脚本时,是按块来执行的。通俗地说,就是浏览器在解析HTML文档流时,如果遇到一个

// JavaScript代码块2

var a =1;

function f;

}

虽然说,JavaScript是按块执行的,但是不同块都属于同一个全局作用域,也就是说,块之间的变量和函数是可以共享的。

1.4 借助事件机制改变JavaScript执行顺序

由于JavaScript是按块处理代码,同时又遵循HTML文档流的解析顺序,所以在上面示例中会看到这样的语法错误。但是当文档流加载完毕,如果再次访问就不会出现这样的错误。例如,把访问第2块代码中的变量和函数的代码放在页面初始化事件函数中,就不会出现语法错误了。

复制代码 代码如下:

// JavaScript代码块1

window.onload = function(){ // 页面初始化事件处理函数

alert;

}

// JavaScript代码块2

var a =1;

function f;

}

为了安全起见,我们一般在页面初始化完毕之后才允许JavaScript代码执行,这样可以避免网速对JavaScript执行的影响,同时也避开了HTML文档流对于JavaScript执行的限制。

注意

如果在一个页面中存在多个windows.onload事件处理函数,则只有最后一个才是有效的,为了解决这个问题,可以把所有脚本或调用函数都放在同一个onload事件处理函数中,例如:

复制代码 代码如下:window.onload = function;

f2;

}

而且通过这种方式可以改变函数的执行顺序,方法是:简单地调整onload事件处理函数中调用函数的排列顺序。

除了页面初始化事件外,我们还可以通过各种交互事件来改变JavaScript代码的执行顺序,如鼠标事件、键盘事件及时钟触发器等方法,详细讲解请参阅第14章的内容。

1.5 JavaScript输出脚本的执行顺序

在JavaScript开发中,经常会使用document对象的write()方法输出JavaScript脚本。那么这些动态输出的脚本是如何执行的呢?例如:

复制代码 代码如下:document.write('

');

document.write('

');

document.write('

alert;

外部JavaScript文件的代码如下所示。复制代码 代码如下:var n = 1;

alert;

在IE浏览器中的执行顺序如图1-6所示。

图1-6 IE 7浏览器的执行顺序和提示的语法错误

在符合DOM标准的浏览器中的执行顺序与IE浏览器不同,且没有语法错误,如图1-7所示的是在Firefox 3.0浏览器中的执行顺序。

图1-7 Firefox 3浏览器的执行顺序和提示的语法错误

解决不同浏览器存在的不同执行顺序,以及可能存在Bug。我们可以把凡是使用输出脚本导入的外部文件,都放在独立的代码块中,这样根据上面介绍的JavaScript代码块执行顺序,就可以避免这个问题。例如,针对上面示例,可以这样设计:

复制代码 代码如下:

document.write('

');

document.write('

alert; // 提示5

这样在不同浏览器中都能够按顺序执行上面代码,且输出顺序都是1、2、3、4和5。存在问题的原因是:输出导入的脚本与当前JavaScript代码块之间的矛盾。如果单独输出就不会发生冲突了。

下一篇:没有了

更多新闻推荐

Copyright © 2015-2019 http://www.77zhth.net. 美高梅官方网站66159有限公司 版权所有