摘要:学习 Function 与 eval
Function
Function 构造函数创建一个新的 Function 对象,他只在全局作用域中运行,而不能访问 Function 构造器被调用生成的上下文的作用域。每个 JavaScript 函数实际上都是一个 Function 对象。
使用 Function 构造器生成的 Function 对象比使用函数声明或函数表达式更为低效,因为 Function 构造器创建的函数是在函数创建时跟其他代码一起解析的
语法
1 | new Function ([arg1[, arg2[, ...argN]],] functionBody) |
前面的参数 arg1, arg2, ... argN
是创建函数时传递的参数,要保证这些参数的命名必须合法。functionBody
则是包含函数定义的字符串
调用 Function 创建函数时,有没有关键词 new 都可以
属性和方法
全局的 Function 对象没有自己的属性和方法,但它可以从原型对象 Function.prototype 上继承一些属性和方法。比如 lenght 属性
1 | console.log(Function.prototype.length) // 0 |
注意:length 是函数对象的一个属性值,指该函数有多少个必须要传入的参数,即形参的个数。形参的数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数,而 arguments.length
是函数调用时实际传参个数
1 | console.log((function(){}).length) // 0 |
Function.prototype.constructor
指向声明函数的原型构造方法,但是它可以修改,易于伪造
还有一些常见的方法
Function.prototype.apply:可以在一个对象的上下文中使用另一个对象的方法,参数以数组的形式传入
Function.prototype.call:同 apply,但参数以列表的形式传入
Function.prototype.bind:创建一个新函数,称为绑定函数。调用这个绑定函数时,绑定函数会以传入的第一个参数作为 this,传入的其他参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数
详细查看模拟实现call、applay、bind和new了解三者的原理
Function.prototype.toString:获取函数的实现源码的字符串,它覆盖了 Object.prototype.toString 方法
eval
eval() 是全局对象的一个函数属性,它会将传入的字符串当做 JavaScript 代码进行执行,然后返回字符串中代码的返回值。如果返回值为空,则返回 undefined。如果字符串表示的是表达式,eval 会对表达式进行求值,因为 JavaScript 可以自动为算术表达式求值。如果参数表示的是 JavaScript 语句,eval 就会执行这些语句。如果参数不是字符串,eval 会将参数原封不动的返回
1 | eval("1 + 2") // 返回:3 |
如果是间接调用 eval 函数,它将使用全局作用域
1 | var x = 1, y = 2; |
永远不要使用 eval
eval 使用与调用者相同权限执行代码,容易被恶意修改。 eval 通常比其他替代方法更慢,因为它必须调用 JS 解释器,而其他结构大多会被 JS 引擎优化。使用 window.Function 替代 eval
要注意: Function 是全局作用域,而 eval 可以访问当前作用域
1 | // eval 全局作用域下调用 Date |