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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 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语句定义的函数称为命名式函数、声明式函数或函数常量,而通过匿名方式定义的函数称为引用式函数或函数表达式,而把赋值给变量的匿名函数称为函数对象,把该变量称为函数引用。

相关文章
|
3月前
|
存储 JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果+1
JavaScript编程实现tab选项卡切换的效果+1
|
1月前
|
前端开发 JavaScript 持续交付
提高JavaScript编程效率
提高JavaScript编程效率
28 3
|
1月前
|
JavaScript 前端开发
JS中的构造函数的含义和用法
构造函数是JavaScript中用于创建新对象的特殊函数,通常首字母大写。通过`new`关键字调用构造函数,可以初始化具有相同属性和方法的对象实例,从而实现代码复用。例如,定义一个`Person`构造函数,可以通过传入不同的参数创建多个`Person`对象,每个对象都有自己的属性值。此外,构造函数还可以包含方法,使每个实例都能执行特定的操作。构造函数的静态属性仅能通过构造函数本身访问。ES6引入了`class`语法糖,简化了类的定义和实例化过程。
31 1
|
1月前
|
存储 前端开发 JavaScript
JavaScript常用的内置构造函数
JavaScript提供的内置构造函数在数据处理、对象创建、异常处理和异步操作等方面发挥了重要作用。掌握这些构造函数及其用法,对于开发高效、可靠的JavaScript应用至关重要。通过合理使用这些内置构造函数,开发者可以更好地管理和操作各种类型的数据,提升开发效率和代码质量。
25 1
|
1月前
|
自然语言处理 JavaScript 前端开发
JavaScript闭包:解锁编程潜能,释放你的创造力
【10月更文挑战第25天】本文深入探讨了JavaScript中的闭包,包括其基本概念、创建方法和实践应用。闭包允许函数访问其定义时的作用域链,常用于数据封装、函数柯里化和模块化编程。文章还提供了闭包的最佳实践,帮助读者更好地理解和使用这一强大特性。
23 2
构造函数(function)可以使用 new 生成实例,箭头函数可以吗
构造函数使用 `new` 关键字可以生成实例对象,而箭头函数则不能用作构造函数,因为它没有自己的 `this` 上下文,使用 `new` 调用会抛出错误。
|
3月前
|
JavaScript 前端开发
一个js里可以有多少个async function,如何用最少的async function实现多个异步操作
在 JavaScript 中,可以通过多种方法实现多个异步操作并减少 `async` 函数的数量。
|
3月前
|
JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果
JavaScript编程实现tab选项卡切换的效果
|
3月前
|
JavaScript 前端开发
用JavaScript编程控制网页上checkbox选择状态:全选、全部取消、反选
用JavaScript编程控制网页上checkbox选择状态:全选、全部取消、反选
|
3月前
|
JavaScript 前端开发 安全
JavaScript编程实现字符和字符串翻转
JavaScript编程实现字符和字符串翻转