[译]JavaScript:void运算符

原文:http://www.2ality.com/2011/05/void-operator.html


语法

void expr

void运算符的作用是:计算表达式expr,并返回undefined.例子:

> void 0
undefined
> void(0)
undefined

> void 4+7 // 由于void比+优先级更高,所以该表达式被解析为(void 4)+7 NaN
> void(4+7)
undefined

> var x;
> x = 3;
3
> void(x = 5);
undefined
> x
5

void是个运算符,而不是函数,它不能被重新定义,如果自定义一个void函数,会抛出异常,像下面这样:

>function void(expr) { // 这里会报错
     return undefined;
}
SyntaxError: Unexpected token void

译者注:在Firefox中,上面的代码只有在严格模式下才会报错,其他的关键字和保留关键字作为函数声明的函数名时也一样.

>function void(expr) { // 没有报错,但不会真正声明一个void函数
     return undefined;
}

>function void(expr) { // 严格模式下会报错
"use strict";
return undefined;
}
SyntaxError: redefining
void is deprecated

>function class(expr) { // class也是个保留关键字
"use strict";
return undefined;
}
SyntaxError: redefining
class is deprecated

void的三种用途.

本文剩余的部分讲讲void运算符的三种用途:

  1. void 0代替undefined
  2. 书签小程序
  3. 在链接中执行JavaScript代码

用途1: 用void 0代替undefined

void 0或者void(0)总是等于undefined,只有一个例外:undefined被重新赋值的时候:

> function a(undefined) { return undefined; }   //这里的undefined是个局部变量
> a("hello")
’hello’

> undefined = "foo";   //这个undefined实际上是window.undefined
> console.log(undefined);
foo

void不用担心被重新赋值:

> function b() { var void = function() {}; return void(0); }
missing variable name
function b() { var void = function() {}; return void(0); }
.......................
^

> void = "foo";
syntax error
void = "foo";
......
^

译者注:通常使用的undefined实际上就是window.undefined(属性名和值的名称相同,window.NaN,window.Infinity也类似),它是一个全局变量,在ES3的引擎上,这个变量可以被修改.而在ES5的引擎上,它是window的只读属性,不能被重新赋值,只是在非严格模式下,该赋值操作会静默失败,而在严格模式下,会抛出异常.

Firefox3.6下(只实现了部分ES5特性,在这里算是ES3引擎)

>undefined = true;
>console.log(undefined);
true

Firefox18下(完全实现了ES5)

>(function () {
     undefined = true;  // 没有报错,但其实没有赋值成功
   console.log(undefined);
})()
undefined 

>(function () {
    "use strict";
     undefined = true;  // 严格模式,为只读属性赋值会抛出异常
})()
TypeError: "undefined" is read-only

如果你无论如何都担心全局的undefined变量会被别人修改,那就使用void 0.否则,使用让人更容易明白的undefined,因为并不是所有阅读你的代码的人都熟悉void运算符.

译者注:现在很流行的做法是把自己的代码都写在一个自执行的函数表达式里,函数内部使用一个局部的undefined变量,这样可以保证undefined变量的值是真实的undefined.

//ES3引擎下
>undefined = true;
>console.log(undefined)
true
>(function (undefined) {
    console.log(undefined)  //undefined是个参数,但没有传入对应的实参,因此它的值就是真实的undefined
})()
undefined

用途2: 书签小程序

书签小程序(Bookmarklets)是一个能够执行JavaScript代码的URI(译者注:使用JavaScript伪协议).如果一个bookmarklet返回的结果不是undefined,那么当前页面显示的内容会被这个返回值替代.这时候就得用到void运算符.[Webkit内核的浏览器不会有这样的麻烦]:

  • javascript:3+4 会把当前页面的内容替换成7.
  • javascript:void(3+4) 不会改变当前页面的内容.void会“隐藏”掉表达式3+4的结果.

类似的:

  • javascript:window.open("http://www.whitehouse.gov/") 会替换掉当前页面的内容.
  • javascript:void window.open("http://www.whitehouse.gov/") 不会改变当前页面的内容.

更复杂的例子:这个bookmarklet可以把当前页面的URL提交到submit.example.com:

javascript:void window.open("http://submit.example.com/submit?"+encodeURIComponent(document.location.href))

这个bookmarklet不会改变当前页面的内容,会在新标签或新窗口中打开页面.

译者注:网上有很多流行的Bookmarklet,通常是导入了另外一个js文件,比如繁体字转换成简体字,比如购物网站比价.

javascript: void(document.body.appendChild(document.createElement("script")).src = "http://tongwen.openfoundry.org/NewTongWen/tools/bookmarklet_cn2.js")

用途3: 在链接中执行JavaScript代码

虽然这种做法是不推荐的,但的确是可行的,例如下面的代码:

<a href="javascript:void computeResult()">Compute</a>

如果函数computeResult()返回undefined(或者没有return语句,也默认返回undefined),则不会有什么事.但如果这个函数返回了其他的值,那么你必须在函数前面添加void运算符来防止它改变当前页面的内容.[Webkit内核的浏览器不会有这样的麻烦].

译者注:更常见的用法是:javascript:void(0),用来阻止链接默认的跳转行为.

posted @ 2012-09-23 16:55  紫云飞  阅读(4651)  评论(1编辑  收藏  举报