下面我把要点简单翻译一下,不做扩展解释.
with语句
为什么不去使用它?
1.意外的运行结果,可能隐式创建全局变量
2.闭包作用域解析过多消耗
3.后期编译
有人说,es5的严格模式可以防止隐式创建全局变量(不用var),这样能减少with的一个问题.但是…
严格模式也不能使用with啊.
为什么说它是有用的?
1.构建浏览器开发者工具
//chrome developer tools
is._evaluateon =
function(evalfunction, obj, expression) {
is._ensurecommandlineapiinstalled();
expression =
with (window._inspectorcommandlineapi) {\
with (window) { + expression + } };
return evalfunction.call(obj, expression);
}
2.模拟块级作用域
//是的,还是这个老掉牙的问题
var addhandlers = function(nodes) {
for (var i = 0; i < nodes.length; i++) {
nodes[i].onclick =
function(e) {alert(i);}
}
};
//你可以通过在外面包一个函数来解决
var addhandlers = function(nodes) {
for (var i = 0; i < nodes.length; i++) {
nodes[i].onclick = function(i) {
return function(e) {alert(i);};
}(i);
}
};
//或者使用'with'来模拟块级作用域
var addhandlers = function(nodes) {
for (var i = 0; i < nodes.length; i++) {
with ({i:i}) {
nodes[i].onclick =
function(e) {alert(i);}
}
}
};
eval语句
为什么不去使用它?
1.代码注入
2.无法进行闭包优化
3.后期编译
为什么说它是有用的?
1. json.parse不可用的时候
有人在stack overflow上说:
“javascript的eval是不安全的,使用json.org上的json解析器来解析json”
还有人说:
“不要使用eval来解析json!用道格拉斯写的json2.js!”
可是:
// from json2.js
if (/^[\],:{}\s]*$/
.test(text.replace(/*regex*/, '@')
.replace(/*regex*/, ']')
.replace(/*regex*/, ''))) {
j = eval('(' + text + ')');
}
2.浏览器的javascript控制台都是用eval实现的
在webkit控制台或jsbin中执行下面的代码
>(function () {
console.log(string(arguments.callee.caller))
})()
function eval() {
[native code]
}
john resig说过:
“eval和with是被轻视的,被误用的,被大部分javascript程序员公然谴责的,但如果能正确使用的话,可以用它们写出一些奇妙的,无法用其他功能实现的代码”
function构造函数
为什么说它是有用的?
1.代码运行在可预见的作用域内
2.只能动态创建全局变量
3.不存在闭包优化的问题
用在了什么地方?
1. jquery的parsejson
// jquery parsejson
// logic borrowed from http://json.org/json2.js
if (rvalidchars.test(data.replace(rvalidescape,@)
.replace( rvalidtokens,])
.replace( rvalidbraces,))) {
return ( new function( return + data ) )();
}
2.underscore.js的字符串内插
//from _.template
// if a variable is not specified,
// place data values in local scope.
if (!settings.variable)
source = 'with(obj||{}){\n' + source + '}\n';
//..
var render = new function(
settings.variable || 'obj', '_', source);
==运算符
为什么不去使用它?
1.强制将两边的操作数转换为相同类型
为什么说它是有用的?
1.强制将两边的操作数转换为相同类型
2.undefined == null
//这样写是不是很麻烦
if ((x === null) || (x === undefined))
//完全可以下面这样写
if (x == null)
3.当两边的操作数类型明显相同时使用
typeof thing == function; //typeof运算符肯定返回字符串
myarray.length == 2; //length属性肯定返回数字
mystring.indexof('x') == 0; //indeof方法肯定返回数字
真值不一定==true,假值不一定==false
if (potato) {
potato == true; //false
}
array构造函数
为什么不去使用它?
1.new array()也是evil的?jslint也推荐使用[].
为什么说它是有用的?
//from prototype.js extension of
//string.prototype
function times(count) {
return count < 1 ?
'' : new array(count + 1).join(this);
}
'me'.times(10); //memememememememememe
其他
不要扩展原生的原型对象
(es 5 shims都这么干)
在for/in遍历时总要使用hasownproperty
(在没有扩展对象原型的前提下没有必要这么做)
把所有的var语句放在顶部
(for语句还是放在初始化表达式中好)
要在调用函数之前先声明函数
(在优先考虑实现细节时使用)
不要使用逗号运算符
(在使用多个表达式时的时候可以使用)
使用parseint时总要把第二个参数指定为10
(除非字符串以‘0’或‘x’开头,否则没必要)
译者注
上面说了这么多,我自己也想到一个被误解的东西,那就是escape.网上有不少人说:“不要使用escape”.
为什么说它是有用的?
1.escape转义的字符更多,有时候需要转义后两个函数不转义的字符.
ascii char escape() encodeuri() encodeuricomponent()
! %21 ! !
# %23 # %23
$ %24 $ %24
& %26 & %26
‘ %27 ‘ ‘
( %28 ( (
) %29 ) )
+ + + %2b
, %2c , %2c
/ / / %2f
: %3a : %3a
; %3b ; %3b
= %3d = %3d
? %3f ? %3f
@ @ @ %40
~ %7e ~ ~
2.将字符串转换为utf8编码,通常用在base64的时候.
escape相当于是在utf16编码的字符串上转义,encodeuricomponent相当于是先把utf16的字符串转换成utf8编码后再escape.
encodeuricomponent(str) === escape(utf16toutf8(str))
可以推导出utf16toutf8(str) === unescape( encodeuricomponent( str )
然后就能用在base64编码的时候,比网上看到的那些简单多了吧.注意btoa和atob有兼容问题.
function base64encode(str) {
return btoa(unescape(encodeuricomponent(str)));
}
function base64decode(str) {
return decodeuricomponent(escape(atob(str)));
}
