惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

囧克斯

奔四了,写给40岁的自己 有序退网 我和 Vue.js 的十年 我参与《代码之外 Beyond Code》的故事 博客站迁移至 VitePress 的备忘 写给我的奶奶 中文格式化小工具 zhlint 及其开发心得 vue-mark-display:用 markdown 语法轻松撰写幻灯片 我对技术会议的一些看法 VueConf Hangzhou 见闻 第四届 CSSConf CN 见闻 [译]Web 表单的未来 [译]苹果正在做一些他们的程序员明摆着不想要的东西 [译]为什么我不会无偿加班且你也不应该 寄语应届生:走出校园的几个人生转变 [译]如果管理是唯一可走的路,那就完蛋了 [译]如何撰写 Git 提交信息 [译]C 程序的原则 Vue 2.0 来了! Weex 近 4 个月的开源之路 Weex 在 JS Runtime 内的多实例管理 我理解的 SPA 我理解的 Flux 架构 【整理】Vue 2.0 自 beta 1 到 beta 4 以来的主要更新 通过一张图走进 Vue 2.0 Code Review for Vue 2.0 Preview Vue 2.0 发布啦! 务实的小而美 Vue.js 1.0.0 发布了! [译]如何成为一名卓越的前端工程师 手机淘宝前端的图片相关工作流程梳理 [译]如何让办公室政治最小化 Vue.js 源码学习笔记 从原型到发布——“团队时间线” 1.0 开发心得 Vue + webpack 项目实践 用 Koa 写服务体验 webcomponents 笔记 之 配置管理 14}, {15 小秀个人的13~14年摄影作品 (共19张) 由今年D2前端论坛想到的 [译]CSS命名神马的真心难 [译]Git 分支的最佳实践 [译]撰写可测试的 JavaScript [译]语义化版本管理 [译]通过HTML5 Canvas API调节图像的亮度和颜色 [译]JavaScript V8性能小贴士 [译]视觉差,走起! [译]Chrome开发者工具中评估性能的五大新特性 精气神儿 细节无微不至,彩屏让人又爱又恨——新老“神机”大对决:Nokia 1050 vs Nokia 1202 秦升拿到红牌之后…… 用Sass重新整理自己的博客主题样式 Connect中间件使用手册 实践 巧用 RequireJS Optimizer 给传统的前端项目打包 编辑器小调查结果 [译]JSLint 文档 烟火——写给蛇年的傲游和我 小秀个人的全年摄影作品 (共15张) 2012年终毫无正能量的总结 标签?ID?还是CLASS? 微创新=伪创新 HTML5峰会归来 分享bookmarklet一则:随意阅读 国际羽联和中国队之间的恶性循环 ZeroClipboard 学习笔记 “思考人生” 听杨东杰弹吉他 学习精髓 网站装修笔记20120426 网站装修笔记20120414 网站装修笔记20120406 分享Typecho插件:百度统计助手 我的得奖感言 网站装修笔记20120331 用CSS3制作尖角标签按钮样式 分享Typecho插件:Markdown 解析器 + 编辑器 分享Typecho皮肤:我的字很大 汇总自己过去的一些HTML5科普文章 html5中的消息通信简介 + 我的新网站开张 网站装修计划 Typed Arrays 是神马? Hello World 文明看球 HTML5中的文件处理 之 File Writer API HTML5中的文件处理 之 File API 独生子女、互相等和不耐烦 IndexedDB技术简介(四) IndexedDB技术简介(三) IndexedDB技术简介(二) IndexedDB技术简介(一) 把博客的字体进一步调大,同时去掉了侧边栏 “模仿别人是为了找到自己” 写给我未婚妻的2011年 写给自己的2011年 手把手教你入门EaselJS做HTML5动画 “吃了吧,不吃就浪费了” 写给傲游的2011年 所谓专业 写给HTML5的2011年
记解答QQ群里的一个JavaScript问题
勾三股四 · 2011-03-13 · via 囧克斯

本文摘自 勾三股四 更早时期的 不老歌 博客。


问题是这样的:

window.onload = function () {
    var jsonStr = '{"name": "w", "sex": "male"}';

    //method 1
    var json = (new Function("return " + jsonStr))();

    //method 2
    function strToJson(str) {
        return str;
    };
    var json = new strToJson(jsonStr);
}

问 method 2 为什么不能达到 method 1 的效果?

大家觉得对于这样的问题该如何解答呢?

我是这么分析的。

new Function('...')

首先我觉得这位朋友对 new Function('...') 的意思没有完全理解正确。这句话是用来定义一个函数的,换句话说:

var funcName = new Function('return 1;');

相当于:

function funcName() {return 1;}

如果这两句 js 等价可以理解的话,那么 method 1 就等价于:

var json = (function () {return {"name": "w", "sex": "male"}})()

(function () {...})()

如果还看得不明白,那么这位朋友对匿名函数的定义和调用可能也不熟悉。比如:

function funcName() {return 1;}
var a = funcName();

相当于:

var a = (function funcName() {return 1;})();

进而:

var a = (function () {return 1;})();

所以 method 1 又可以进一步等价于

function funcName() {return {"name": "w", "sex": "male"}}
var json = funcName();

(function () {...})()写法的好处在哪里?

如果大家接触的js略微深入一些,会发现如今的js代码里已经大量存在(function () {...})()这样的用法了——包括一些比较复杂的函数。那么大家为什么都这么用呢?好处在哪里呢?
这种写法相比较先定义一个有名字的函数,再执行这个函数的写法相比,有一个比较明显的区别,就是你不需要为执行的函数起名字。这样的好处是这段函数的定义不会污染命名空间。
那你可能还有另外一个疑问,我不写成函数,直接写函数里的代码让它执行不就行了吗?如果要回答这个问题,我们需要引入更复杂的函数,比如:

(function () {var a = ...; ...})()

如果把函数里的代码直接写在外面:

var a = ...;
...

这样的话,命名空间会被函数定义中的局部变量所污染。而上一种写法可以使你尽情的使用局部变量而不会有命名空间被污染的后顾之忧。
所以综合两方面的优势,(function () {...})()算是一个两全其美的写法,它也因此被广泛运用了起来。

如果对 method 1 有足够深入和准确的认识,那么 method 2 显然是做不到 method 1 相同的结果的。而且 method 2 中的 strToJson 是一个普通的执行函数而不是构造函数,在这里用 new strToJson() 当构造函数创建对象就更杯具了,离 method 1 的思路也越来越远了。

这里想提醒大家的是,(new Function(...))() 的代码执行方式和 eval(...) 有异曲同工之妙,都是将字符串当做脚本来执行。我们平时对于 eval 的使用时很谨慎的,而 new Function 则见得非常少,也几乎不会主动去使用,其实在实际运用的时候需要和 eval 同等对待但它和(function () {...})()的道理相同,会比eval更好的解决命名空间被污染的问题(感谢egg的补充)。