JS编程建议——57:禁用Function构造函数

简介: 57:禁用Function构造函数

建议57:禁用Function构造函数
定义函数的方法包括3种:function语句、Function构造函数和函数直接量。不管用哪种方法定义函数,它们都是Function对象的实例,并将继承Function对象所有默认或自定义的方法和属性。
// 使用function语句编写函数
function f(x){

return x;

}
// 使用Function()构造函数克隆函数
var f = new Function("x", "return x;");
// 使用函数直接量直接生成函数
var f = function(x){

return x;

}
虽然这些方法定义函数的结构体相同,函数的效果相近,但是也存在很多差异,详细比较见表3.1。
表3.1 函数定义方法比较
使用function语句 使用Function构造函数 使用函数直接量
兼容 完全 JavaScript 1.1及以上 JavaScript 1.2及以上
形式 句子 表达式 表达式
名称 有名 匿名 匿名
主体 标准语法 字符串 标准语法
性质 静态 动态 静态
解析 以命令的形式构造一个函数对象 解析函数体,能够动态创建一个新的函数对象 以表达式的形式构造一个函数对象
(1)作用域比较
使用Function构造函数创建的函数具有顶级作用域,JavaScript解释器也总是把它作为顶级函数来编译,而function语句和函数直接量定义的函数都有自己的作用域(即局部作用域,或称为函数作用域)。例如:
var n = 1;
function f(){

var n = 2;
function e(){
    return n;
}
return e;

}
alert(f()()); //2
在上面示例中,分别在函数体外和函数体内声明并初始化变量n,然后在函数体内使用function语句定义一个函数e,定义该函数返回变量n的值。最后在函数体外调用函数的返回函数。通过结果可以发现,返回值为局部变量n的值(即为2),也就是说,function语句定义的函数拥有自己的作用域。同理,如果使用函数直接量定义函数e,当调用该返回函数时,返回值是2,而不是1,那么也说明函数直接量定义的函数拥有自己的作用域。
但是,如果使用Function构造函数定义函数e,则调用该返回函数时,返回的值是1,而不再是2了,看来Function构造函数定义的函数作用域需要动态确定,而不是在定义函数时确定的,代码如下:
var n = 1;
function f(){

var n = 2;
var e = new Function("return n;");
return e;

}
alert(f()()); //1
(2)解析效率比较
JavaScript解释器在解析代码时,并非一行行地分析和执行程序,而是一段段地分析执行。在同一段代码中,使用function语句和函数直接量定义的函数结构总会被提取出来优先执行。只有在函数被解析和执行完毕之后,才会按顺序执行其他代码行。但是使用Function构造函数定义的函数并非提前运行,而是在运行时动态地被执行,这也是Function构造函数定义的函数具有顶级作用域的根本原因。
从时间角度审视,function语句和函数直接量定义的函数具有静态的特性,而Function构造函数定义的函数具有动态的特性。这种解析机制的不同,必然带来不同的执行效率,这种差异性可以通过将一个循环结构放大来比较得出。
在下面这个示例中,分别把function语句定义的空函数和Function构造函数定义的空函数放在一个循环体内,让它们空转十万次,这样就会明显感到使用function语句定义的空函数运行效率更高。
// 测试function语句定义的空函数执行效率
var a = new Date();
var x = a.getTime();
for(var i=0;i<100000;i++){

function(){   //使用function语句定义的空函数
    ;
}

}
var b = new Date();
var y = b.getTime();
alert(y-x); //62,不同环境和浏览器会存在差异
// 测试Function构造函数定义的空函数执行效率
var a = new Date();
var x = a.getTime();
for(var i=0;i<100000;i++){

new Function();  //使用Function构造函数定义的空函数

}
var b = new Date();
var y = b.getTime();
alert(y-x); //2390
JavaScript解释器首先把function语句定义的函数提取出来进行编译,这样每次循环执行该函数时,就不再从头开始重新编译该函数对象了,而Function构造函数定义的函数每次循环时都需要动态编译一次,这样效率就非常低了。
(3)兼容性比较
从兼容角度考虑,使用function语句定义函数不用考虑JavaScript版本问题,所有版本都支持这种方法。而Function构造函数只能在JavaScript 1.1及其以上版本中使用,函数直接量仅在JavaScript 1.2及其以上版本中有效。当然,版本问题现在已经不是问题了。
Function构造函数和函数直接量定义函数方法有点相似,它们都是使用表达式来创建的,而不是通过语句创建的,这样带来了很大的灵活性。对于仅使用一次的函数,非常适合使用表达式的方法来创建。
由于Function构造函数和函数直接量定义函数不需要额外的变量,它们直接在表达式中参与运算,所以节省了资源,克服了使用function语句定义函数占用内存的弊端,也就是说,这些函数运行完毕即被释放而不再占用内存空间。
对于Function构造函数来说,由于定义函数的主体必须以字符串的形式来表示,使用这种方法定义复杂的函数就显得有点笨拙,很容易出现语法错误。但函数直接量的主体使用标准的JavaScript语法,这样看来使用函数直接量是一种比较快捷的方法。
通过function语句定义的函数称为命名式函数、声明式函数或函数常量,而通过匿名方式定义的函数称为引用式函数或函数表达式,而把赋值给变量的匿名函数称为函数对象,把该变量称为函数引用。

相关文章
|
10天前
|
设计模式 JavaScript 前端开发
在JavaScript中,继承是一个重要的概念,它允许我们基于现有的类(或构造函数)创建新的类
【6月更文挑战第15天】JavaScript继承促进代码复用与扩展,创建类层次结构,但过深的继承链导致复杂性增加,紧密耦合增加维护成本,单继承限制灵活性,方法覆盖可能隐藏父类功能,且可能影响性能。设计时需谨慎权衡并考虑使用组合等替代方案。
31 7
|
8天前
|
数据采集 JavaScript 前端开发
理解并应用:JavaScript响应式编程与事件驱动编程的差异
了解JavaScript的响应式编程与事件驱动编程至关重要。事件驱动编程基于事件触发函数执行,如用户交互或系统事件。响应式编程则关注数据流变化,利用Observables自动响应更新。在爬虫代理IP的Web Scraping示例中,两者分别通过axios和rxjs显示了数据抓取的不同处理方式。掌握这两者能提升异步操作的效率和代码质量。
理解并应用:JavaScript响应式编程与事件驱动编程的差异
|
13天前
|
JSON JavaScript 前端开发
Node.js命令大全:让你的编程效率翻倍
探索Node.js常用命令!本文作者木头左带你了解文件操作:`ls`、创建/删除文件夹、复制/移动文件及读写文件内容。此外,还介绍了查看系统信息、CPU和内存详情的方法。一起提升Node.js开发效率![[1](https://mutouzuo.oss-cn-hangzhou.aliyuncs.com/my/mudouzuo1.png)]
Node.js命令大全:让你的编程效率翻倍
|
3天前
|
JavaScript 前端开发
JavaScript函数是代码复用的关键。使用`function`创建函数
【6月更文挑战第22天】JavaScript函数是代码复用的关键。使用`function`创建函数,如`function sayHello() {...}`或`function addNumbers(num1, num2) {...}`。调用函数如`sayHello()`执行其代码,传递参数按值进行。函数可通过`return`返回值,无返回值默认为`undefined`。理解函数对于模块化编程至关重要。
16 4
|
4天前
|
JavaScript 前端开发
JavaScript进阶-Class与模块化编程
【6月更文挑战第21天】**ES6引入Class和模块化,提升JavaScript的代码组织和复用。Class是原型机制的语法糖,简化面向对象编程。模块化通过`import/export`管理代码,支持默认和命名导出。常见问题包括`this`指向和循环依赖。理解这些问题及避免策略,能助你写出更高效、可维护的代码。**
|
2天前
|
JSON JavaScript 前端开发
Javascript 模块化编程的方法和代码
Javascript 模块化编程的方法和代码
11 1
|
27天前
|
JavaScript Java 测试技术
基于springboot+vue.js的编程训练系统附带文章和源代码设计说明文档ppt
基于springboot+vue.js的编程训练系统附带文章和源代码设计说明文档ppt
32 11
|
1月前
|
JavaScript
js中如何使用工厂方式和构造函数创建对象,web开发项目实例
js中如何使用工厂方式和构造函数创建对象,web开发项目实例
|
1月前
|
消息中间件 存储 设计模式
JavaScript发布订阅模式:实现事件驱动编程!
JavaScript发布订阅模式:实现事件驱动编程!
|
1月前
|
JavaScript 前端开发 数据处理
掌握JavaScript中的二进制运算,提升你的编程技能!
掌握JavaScript中的二进制运算,提升你的编程技能!

热门文章

最新文章