关于事件传播的三个阶段

事件传播分为三个阶段:事件捕获,目标对象本身的事件程序,事件冒泡。

事件传播的捕获阶段像反向的冒泡阶段。最先调用Window对象的捕获处理程序,接着是body对象的,再然后是 DOM 树向下,以此类推,直到调用事件目标的父元素的捕获事件处理程序。在目标对象本身上注册的捕获事件处理程序不会被调用。

addEventListener()把一个布尔值作为其第三个参数。如果这个参数是true,那么事件处理程序被注册为捕获事件处理程序,它会在事件传播的第一个阶段调用。事件冒泡得到广泛的支持,它能用在包括 IE 在内的所有浏览器中,且无论事件处理程序以哪种方式注册(除非它们被注册为捕获事件处理程序)。而事件捕获只能用于以addEventListener()注册且第三个参数是true的事件处理程序中。这意味着事件捕获无法在 IE9 之前的 IE 中使用。

查看全文

CSS 的后代伪类选择器用法浅析

CSS 的后代伪类选择器共五对,两种类型(我命名为:child 型与 type 型),分别是:

child 型 type 型
:first-child :first-of-type
:last-child :last-of-type
:only-child :only-of-type
:nth-child(n) :nth-of-type(n)
:nth-last-child(n) :nth-last-of-type(n)

两种类型的主要区别在于查找元素的顺序,child 型先查找元素位置,再查找元素类型;而 type 型则刚好相反,先找类型,后找位置。

查看全文

RESTful Web 服务基础

原文地址 与 译文地址

REST 定义了一组架构原则,您可以根据这些原则设计以系统资源为中心的 Web 服务,包括使用不同语言编写的客户端如何通过 HTTP 处理和传输资源状态。 如果考虑使用它的 Web 服务的数量,REST 近年来已经成为最主要的 Web 服务设计模型。 事实上,REST 对 Web 的影响非常大,由于其使用相当方便,已经普遍地取代了基于 SOAP 和 WSDL 的接口设计。

REST 这个概念于 2000 年由 Roy Fielding 在就读加州大学欧文分校期间在学术论文“ Architectural Styles and the Design of Network-based Software Architectures ”首次提出,他的论文中对使用 Web 服务作为分布式计算平台的一系列软件体系结构原则进行了分析,而其中提出的 REST 概念并没有获得现在这么多关注。 多年以后的今天,REST 的主要框架已经开始出现,但仍然在开发中,因为它已经被广泛接纳到各个平台中,例如通过 JSR-311 成为了 Java™ 6 不可或缺的部分。

本文认为,对于今天正在吸引如此多注意力的最纯粹形式的 REST Web 服务,其具体实现应该遵循四个基本设计原则:

  • 显式地使用 HTTP 方法。
  • 无状态。
  • 公开目录结构式的 URI。
  • 传输 XML、JSON,或同时传输这两者。

下面几个部分将详述这四个原则,并提供技术原理解释,说明为什么这些原则对 REST Web 服务设计人员非常重要。

查看全文

apply() 与 call() 用法浅析

apply()call() 作为所有函数的方法,定义为:在指定this值与参数的情况下调用某个函数或方法。两者的区别是:call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组

这两个方法的关键点在于指定this与参数,所以我们以此为切入点,看看在实际的工作中有哪些用法。

使用apply()支持可变参数

所有的语言,有一些我们经常要做的事情,似乎都被语言的开发人员莫名其妙的忽略了,JavaScript 也不例外。比如查找数组中的最小值与最大值。在 JavaScript 中似乎没有这两种功能,但如果随意探索的话,可能会发现Math对象有两个名为min()max()的方法。

一开始我们认为,这些方法可能就是我们想要的答案,但测试以后,我们发现第个方法都需要可变长度的参数列表,而不是数组。这根本不能满足我们的需求,也就是说,Math.max()的调用,需要像下面这样:

查看全文

JavaScript 中三种转换为数字类型的方式

JavaScript有三种将其它类型转换为数字类型的方式:parseInt()parseFloat()Number()parseInt()parseFloat()只能在 String 类型上调用。而Number()不仅限于 String 类型,比如Date类型上也可以使用。

parseInt()

在判断字符串是否是数字值前,parseInt()parseFloat()都会仔细分析该字符串。

parseInt()方法首先查看位置 0 处的字符,判断它是否是个有效数字;如果不是,该方法将返回NaN,不再继续执行其他操作。但如果该字符是有效数字,该方法将查看位置 1 处的字符,进行同样的测试。这一过程将持续到发现非有效数字的字符为止,此时parseInt()将把该字符之前的字符串转换成数字。

例如,如果要把字符串 “12345red” 转换成整数,那么parseInt()将返回 12345,因为当它检查到字符 r 时,就会停止检测过程。

字符串中包含的数字字面量会被正确转换为数字,比如 “0xA” 会被正确转换为数字 10。不过,字符串 “22.5” 将被转换成 22,因为对于整数来说,小数点是无效字符。

查看全文

HTTP 报文的组成部分

HTTP 报文是简单的格式化数据块。如图一所示,每条报文都包含一条来客户端的请求,或者一条来自客户端的响应。它们由三个部分组成:对报文进行描述的起始行start line)、包含属性的首部header)块,以及可选的,包含数据的主体body)部分。

simple_res_msg
图一:HTTP 报文的三个部分

起始行与首部就是由行分隔的 ASCII 文本。每行都以一个由两个字符组成的行终止序列作为结束,其中包括一个回车符(ASCII 码 13)和一个换行符(ASCII 码 10)。这个行终止符可以写作 CRLF。注意:尽管 HTTP 规范中说明应该用 CRLF 来表示行终止,但稳健的做法也应该接受单个换行符作为行的终止。有些老的,或不完整的 HTTP 应用程序并不总是既发送回车符,又发送换行符。

实体的主体或报文的主体是一个可选的数据块。与起始行和首部不同的是,主体中要k以包含文本或二进制数据,也可以为空。

在图一中,首部给出了一些与主体有关的信息。Content-Type 行说明了主体是什么——在这个图中,就是纯文本文档。Content-Length 行说明了主体有多大,在这里就只有 19 个字符。

查看全文

函数的递归调用

递归(recursion)是经常遇到的一个概念。当函数调用自身,或调用另外一个函数,但这个函数的调用树中的某个地方又调用了自己时,递归就发生了。

对任何类型的程序来说,递归都是一个非常有用的技术——很多数学公式在本质上都是递归。而且,对树进行遍历时,递归也是非常有用的,这是一个可能会在 Web 程序中出现的构造。我们还可以使用递归深入理解函数在 JavaScript 中是如何工作的。

从最简单的开始。

普通命名函数中的递归

有很多常见的递归函数示例。其中一个是用于检测回文——相当于递归技术的“Hello World”。

回文的非递归定义是“一个短语,不管从哪个方向读都是相同的”,我们可以用它来实现一个函数,用于创建反向字符串并和字符串本身进行比较。但是复制字符串从多方面来产不是简洁的解决方案,其中一个原因就是需要分配并创建新的字符串。

通过利用回文的更多数学定义,我们要可以想出一个更简洁的解决方案,这些定义如下所示:

  1. 单个与零个字符都是一个回文。
  2. 如果字符串的第一个字符和最后一个字符相同。将这前后两个排除后,其它的字符串仍是一个回文的话,我们称原字符串是一个回文。

查看全文

闭包与即时函数

有一个重要的构造是在 JavaScript 高级函数式编程中经常使用的,这种构造依赖于对闭包的充分利用,比如:(function(){})()
这种模式的代码,毫无疑问可能用在很多地方,它给 JavaScript 语言带来了出乎意料的能力。让我们分解这段代码,探究其内部到底发生了什么。

首先,先忽略第一组括号的内容,再回头来看代码:(...)()

众所周知,可以通过函数名加圆括号:functionName(),的语法方式调用任意一个函数。但是在这里,我们可以使用任意一个引用函数实例的表达式作为函数的名称。就像下面的代码,使用变量名调用该变量所引用的函数:

与其它表达式在一起使用,我们需要将一个操作符——函数调用操作符 ( ) ,应用在整个表达式上,所以需要用圆括号将该表达式括起来。

也就是说,在 (...)() 中,第一组圆括号仅仅是用于划定表达式的范围,而第二个圆括号则是一个操作符。如下代码,将函数引用通过圆括号括起来是完全合法的:

查看全文

使用闭包实现缓存记忆(memoization)

缓存记忆让函数能够记录它之前被调用时所产生的结果。这样,我们第二次获取结果值时,优先从函数的缓存记录中查找结果,避免重复计算结果。

首先要实例一个无闭包的版本:

查看全文