eval is (always) evil
eval大概也算是整个ECMAScript语言中最强大的一个方法, 他就像是一个完整的ECMAScript解析器。你说它evil,我也承认这个 方法会存在危险,有可能带来安全问题,特别是在用它执行用户输入 数据的情况下。但Wind.js是用eval来运行已经“编译”后的代码, 让你更舒服顺畅的来编写异步回调的代码。这些代码是你自己写的, 所以不必担心代码注入、跨站脚本攻击这样的安全问题。没有这这个 困扰和担忧,我相信eval应该是美好的。
API太丑,eval为什么不封装?
通过eval执行的代码是被认为是包含该次调用的执行环境的一部分, 因此被执行的代码具有与该执行环境有着相同的作用域链。
var Wind = require("wind");
var msg = 'hello world';
eval("console.log(msg)");//hello world
var msg = 'hello world';
var newFunc = eval(Wind.compile("async", function () {
console.log(msg);
}));
newFunc().start();//hello world
变量msg是在eval外定义的,但eval中还是能够打印"hello world"。 如果包装起来如法访问到msg这个变量。
var Wind = require("wind");
var vm = require("vm");
var sandbox = {
Wind: Wind,
console:console
};
function $async(fun){
var script = vm.createScript(Wind.compile("async", fun));
return script.runInNewContext(sandbox);
}
var msg = 'hello world';
var newFunc = $async(function () {
console.log(msg);
});
newFunc().start();//[WARNING] An unhandled error occurred: ReferenceError: msg is not defined
上面的例子中看到我们使用vm模块对eval有一个简单的包装,可以直接 使用$async方法来替换以前的写法。从打印信息中,你很容易看出访问 不到msg这个参数。麻烦请注意一下调用script.runInNewContext()方法 时传入了一个sandbox对象,这相当于往代码运行环境中添加上下文参数。 如果sanbox这个参数不传递,运行上端代码会报ReferenceError: Wind is not defined的错误。这就是eval为什么无法包装的原因。
如果你的代码不需要依赖上下文你可以用上述方法包装,例如这样:
var Wind = require("wind");
var vm = require("vm");
var sandbox = {
Wind: Wind,
console:console
};
function $async(fun){
var script = vm.createScript(Wind.compile("async", fun));
return script.runInNewContext(sandbox);
}
var fib = $async(function () {
$await(Wind.Async.sleep(1000));
console.log(0);
$await(Wind.Async.sleep(1000));
console.log(1);
var a = 0, current = 1;
while (true) {
var b = a;
a = current;
current = a + b;
$await(Wind.Async.sleep(1000));
console.log(current);
}
});
fib().start();
Wind.js很重很慢不适合前端
Wind.js基础组件及异步运行库共计4K大小(Minified + GZipped), Wind.js完全不会给前端带来负担,给你带来顺畅舒服的异步编程体验。
生成的代码看不懂,难以调试
Wind.js生产的代码也完全是Javascript代码,你无需为调试担忧。 下面是一个例子,我相信你很容易就可以看懂。
// Original:
function () {
$await(Wind.Async.sleep(1000));
console.log(0);
$await(Wind.Async.sleep(1000));
console.log(1);
var a = 0, current = 1;
while (true) {
var b = a;
a = current;
current = a + b;
$await(Wind.Async.sleep(1000));
console.log(current);
}
}
// Windified:
/* async << function () { */ (function () {
var _builder_$0 = Wind.builders["async"];
return _builder_$0.Start(this,
_builder_$0.Delay(function () {
/* $await(Wind.Async.sleep(1000)); */ return _builder_$0.Bind(Wind.Async.sleep(1000), function () {
/* console.log(0); */ console.log(0);
/* $await(Wind.Async.sleep(1000)); */ return _builder_$0.Bind(Wind.Async.sleep(1000), function () {
/* console.log(1); */ console.log(1);
/* var a = 0, current = 1; */ var a = 0, current = 1;
return _builder_$0.While(function () {
/* while (true) { */ return true;
},
_builder_$0.Delay(function () {
/* var b = a; */ var b = a;
/* a = current; */ a = current;
/* current = a + b; */ current = a + b;
/* $await(Wind.Async.sleep(1000)); */ return _builder_$0.Bind(Wind.Async.sleep(1000), function () {
/* console.log(current); */ console.log(current);
return _builder_$0.Normal();
});
})
/* } */ );
});
});
})
);
/* } */ })
eval性能方面会有问题
有童鞋提出这方面的问题,但不知道提供什么样子的测试才能令人信服,从而消除疑虑,放心大胆的使用Wind.js。 这个问题还在收集整理中…
写在最后
在ADC被老赵的执着打动了,支持老赵从文档开始吧。 如果你还有对Wind.js的任何疑虑都可以留言,这个文档的目的就是消除你对Wind.js的疑虑。 原帖地址,会不断更新:这里
呵呵,在ADC,吸引最多人的一次演讲确实是老赵的。
多谢支持!
在9月份的沪JS大会上我会想谈Jscex是怎么支持调试的,以及一些JavaScript调试方面一些不太被人关注的地方。接下来一段时间Jscex会有一系列增强调试的功能,说Jscex不容易调试的同学不妨关注一下。
希望有一個jscex的性能測試。
@byvoid 怎么对Jscex的怀疑又到性能上了,很无聊啊。Jscex从来就不是一个会影响性能的东西,你要怎么测试?
@jeffz 我只是心存疑慮啊,不測試怎麼能證明不會影響性能呢?
@byvoid 估计是怀疑eval会影响效率吧。。。。
@zxc122333 eval不会带来效率问题吧!有空搞个专门的测试,你可以把你担心哪个地方性能有问题告诉一下。
@zxc122333 从eval的使用方式就该知道不会影响性能,最后生产环境都不会出现eval……
@byvoid 首先nodejs不是用来写计算密集型应用的,一个IO就打倒千万次方法调用,其次Jscex从理论上说就不会降低性能……你说说你要什么样的测试吧……
弱弱的问下,这个与setTimeout(function(){},mil)
的差别有多大。
说sleep
吗?没差别,sleep
内部就是封装了setTimeout
。
担心eval性能方面会有问题的童鞋,可以提出你的担心纠结的情境
老赵,你可以试着结合一些常用的异步场景,比如mongodb数据库访问,或者异步文件读写做一些压力测试数据,比较wind.js和原生的异步代码性能差别有多大。
意义何在啊,Wind.js又不是搞性能的,纯JS代码转换而已,自动帮你生成回调罢了。
一直有在关注Wind.js, 不过暂时没有应用到.
有个建议, 觉得官方的示例, 太枯燥了,很容易把初学者吓到. 就一个冒泡排序有点孤单, 可以再做几个类似之前blog上改写nodeclub那样的入门教程.
PS: http://windjs.org/cn/docs/async/samples/browser/sorting-animations/ 底部的链接错了.
@jeffz 因为用node.js的大部分都是考虑大并发的情况下,我们公司现在就用node.js做了几个项目都是这样的情况,比如一些对内的api查询接口,wind.js不知道性能损失会有多少,可能我个人比较关注这些吧
@snoopy 如果你了解Wind.js就会知道它不会造成性能损失啊,如果不了解你也不会用是不是……所以我一直觉得做性能测试就是个伪命题……
多谢,一会儿我去改一下。
@jeffz 虽然意义不大, 不过总可以用来吸引一些入门者吧,呵呵.
@atian25 把入门读者吸引歪了没有意义啊……