Javascript 中的 Lambda 表达式

Lambda 表达式是一种简易的函数定义形式,通常在编程语言用来简化代码的结构。比如以下的 Javascript 函数:

在其它语言中的 Lambda 形式为:

Lambda 表达式之所以流行,是因为它可以方便地嵌在其它语句中,比如 Java 8 使用了 Lambda 表达式大规模简化了数组的处理:

Javascript 也终于迎来的 Lambda 表达式,在 ES6 中的定义是“箭头函数”(Arrow Function),第一个例子中的函数可以被简化为:

语法和 C# 类似,而和 Java 不同。

Lambda 表达式基本上可以看成是一个语法糖,但在 EC6 中,它和 function定义的函数有一点点的不一样。你可能已经想到了,就是 this的定义域。看下面的例子:

上面的函数中,一定要使用自定义的 self来把 this传到 .eachfunction中。而使用 Lambda 表达式的话,就不需要这么做了:

箭头函数在 Chrome 45.0 和 Firefox 22.0 以上版本中支持,具体的信息请参考 Arrow functions

Javascript 中判断对象为空

最近写代码的时候碰到这个问题,需要检查一个对象(Object)是否为空,即不包含任何元素。Javascript 中的对象就是一个字典,其中包含了一系列的键值对(Key Value Pair)。检查一个对象是否为空,等价于检查对象中有没有键值对。写成代码,形如:

至于 isEmptyObject 的实现,jQuery 中有一个很有想法的方式,请看代码:

尽管 Javascript 没有原生提供 isEmpty() 方法,但它提供了迭代器,可以用来遍历所有的键值对。于是 jQuery 所做的事情,就是尝试遍历,如果有任何一个键值对,即说明对象非空,直接返回 false。从效率上来说,由于只读取了一个元素,顶多加上一些跳出循环的开销,实际性能不会比原生方法差太多。这是一个非常巧妙的实现。

注:有网友指出 ES5 中提供了 Object.getOwnPropertyNames 方法来获取所有的元素键。它的返回值是一个数组,当数组长度为零时,说明对象为空。

在Javascript中使用String.startsWith和endsWith

在操作字符串(String)类型的时候,startsWith(anotherString)和endsWith(anotherString)是非常好用的方法。其中startsWith判断当前字符串是否以anotherString作为开头,而endsWith则是判断是否作为结尾。举例:

但不幸的是,Javascript中没有自带这两个方法,需要的话只能自己写。当然写起来也不难就是了。

String.slice()和String.substring()类似,都是获得一段子串,但有评测说slice的效率更高。这里不使用indexOf()的原因是,indexOf会扫描整个字符串,如果字符串很长,indexOf的效率就会很差。

和startsWith不一样,endsWith中可以使用indexOf。原因是它只扫描了最后的一段字符串,而比起slice的优势是它不用复制字符串,直接扫描即可,所以效率更高。

强制重定向至HTTPS

有时候需要把网页强制切换成HTTPS,即使用户已经访问了HTTP的版本。原因可能是你不想让用户使用HTTP来访问,因为它不安全。要做到这个很简单,如果不想用PHP或者Apache的mod_rewrite来做这件事,用Javascript也可以。代码如下:

用了这段代码,如果用户访问了如http://leonax.net/...,会被重定向到https://leonax.net/.....。如果想反过来,即把HTTPS强制重定向到HTTP,把targetProtocol的值改成http就行。是不是很方便?

XmlHttpRequest学习笔记 (7) 异步模式

之前提到过,Open()方法的第三个参数Async指定了XmlHttpRequest的通信模式是同步的,还是异步的。当使用异步模式通信的时候,Send()方法会立即返回,而不会等到加载完所有服务器发回的数据才返回。在异步模式下,我们可以通过注册XmlHttpRequest的OnReadyStateChange回调函数来获取它状态的变化,从而做出相应的操作。

来看下面的代码:

这段代码中,当xhr对象的readyState有变化时,xhr会自动调用它的onreadystatechange所对应的方法,也就是那个匿名方法。readyState的值从0到4,分别代表了XmlHttpRequest的5种状态:

  1. 未初始化(Open方法未被调用)
  2. 请求已创建(Open方法已调用,Send方法未调用)
  3. 报头可用(Send方法已调用,并已获得HTTP报头)
  4. 交互中(XmlHttpRequest正在和服务器通信)
  5. 完成(XmlHttpRequest已加载所有数据)

使用异步模式,我们就可以在加载服务器数据的同时,做一些其它的事情,比如显示一个进度条什么的,来提高用户体验。

另外,在异步模式中,可以使用abort方法来中断HTTP请求。

XmlHttpRequest学习笔记 (6) 查看HTTP状态

HTTP状态是HTTP/1.1标准的一部分,它用数字的形式表示了HTTP通信所碰到的问题,比如:

  • 200:成功,即没有碰到任何问题;
  • 301:目标永久转移,以后的HTTP请求可直接发往新的地址;
  • 307:目标暂时转移;
  • 401:未授权,可能需要提供帐号信息;
  • 403:禁止,服务器拒绝响应这个请求;
  • 404:目标未找到;
  • 500:服务器内部错误;

详细的HTTP状态可以参考Wikipedia

在使用XmlHttpRequest做HTTP通信的时候,可以通过下面的属性来获取HTTP状态:

Status
StatusText

Status表示了数字形式的HTTP状态,而StatusText则是字符串形式的。下面是一个例子:

输出:

200 OK
404 Not Found

注意:在send()函数被调用之前,status和statusText是无法被访问的。

XmlHttpRequest学习笔记 (5) HTTP报头

HTTP报头(HTTP Header)是HTTP通信时的一些元数据(Metadata),用来让服务器和客户端达成一些共识,比如客户端的版本、通信内容的格式等。

在使用XmlHttpRequest时,也可以设置或读取HTTP报头,这时可以使用

setRequestHeader方法 和 getResponseHeader方法

先来看setRequestHeader(header, value)方法,它可以用来设置所发出的数据包的报头,比如

设置了Accept-Charset报头为UTF-8,也就是表明客户端支持UTF-8格式的内容,服务器为根据这个设置,来预处理响应的数据包。详细的HTTP报头的定义,可以参考RFC2616的第14节

和setRequestHeader相反,getResponseHeader(header)可用于查询服务器返回的数据包的报头:

假设value的值是"gzip",则说明服务器返回的内容,是使用gzip格式压缩的。

以下是一个样例:

输出为:

iPhone Content length = 30317
IE Content length = 63729

这就说明http://leonax.net/在响应不用的客户端时,返回的数据不一样。

顺便提一下,还有一个方法是getAllResponseHeaders(),可用于获取服务器返回的数据包中所有的报头。

顺便再提一下,一些影响安全性的报头,如Referrer和Content-Length,是不能使用setRequestHeader来设置的。