博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[译]JavaScript:打破所有规则
阅读量:4591 次
发布时间:2019-06-09

本文共 4009 字,大约阅读时间需要 13 分钟。

北京时间今天凌晨,来自Twitter的前端工程师,在柏林举办的JSConf会议上,进行了题为""的演讲,主要讲了一些我们通常认为是错误的不该使用的东西,其实是有用的.本文最下面有演讲用的slides.远在美国的JavaScript之父看了slides也说:我同意其中大部分观点(看来还是有问题?).

下面我把要点简单翻译一下,不做扩展解释.

with语句

为什么不去使用它?

1.意外的运行结果,可能隐式创建全局变量

2.闭包作用域解析过多消耗

3.后期编译

有人说,ES5的严格模式可以防止隐式创建全局变量(不用var),这样能减少with的一个问题.但是...

严格模式也不能使用with啊.

为什么说它是有用的?

1.构建浏览器开发者工具

//Chrome Developer ToolsIS._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.jsif (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.prototypefunction 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.网上有不少人说:.

为什么说它是有用的?

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)));}

 

 

转载于:https://www.cnblogs.com/101rico/archive/2013/02/01/2888592.html

你可能感兴趣的文章
Python复习基础篇
查看>>
关于Cocos2d-x中背景音乐和音效的添加
查看>>
.Net持续集成 —— Jenkins+Git+WebDeploy
查看>>
01_Numpy基本使用
查看>>
checkbox和文字对齐
查看>>
JConsole远程连接配置 服务器监控工具
查看>>
了解HTTP协议栈(实践篇)
查看>>
loj10035. 「一本通 2.1 练习 1」Power Strings
查看>>
%s的用法
查看>>
调用底层不能直接访问的类和方法
查看>>
清理缓存的方法 #DF
查看>>
JAVA array,map 转 json 字符串
查看>>
2017-12-27练习
查看>>
NET设计规范(二) 命名规范
查看>>
VMware 9.0.1安装Mac OS X Mountain Lion 10.8.2
查看>>
SSL延迟
查看>>
android新手关于左右滑动的问题,布局把<android.support.v4.view.ViewPager/><ImageView/> 放在上面就不行了。...
查看>>
深入理解DIP、IoC、DI以及IoC容器
查看>>
赋值文件
查看>>
Vue 数组 字典 template v-for 的使用
查看>>