创建函数 通过构造器的方式来创建函数,最后一个参数为函数体其他为形参
new Function('a','b','alert(a)') /* function anonymous(a,b) { alert(a) } */ 由于函数体是通过字符串拼接的,因此我们可以用这个特性来实现代码的组合
function foo(){ var a = 10; console.log(a); } new Function('say',foo + 'foo();console.log(say)')('Hello foo'); // 10 // Hello foo
// 实际上以上代码是这样的 function anonymous(say) { function foo(){ var a = 10; console.log(a); }foo();console.log(say) } 还可以用这个特性来实现json字符串转对象
var json = '{a:123, b:456}'; new Function('return ' + json)(); // Object {a: 123, b: 456} 甚至我们可以利用它来实现重载运算符
function calc(num1,num2,operator){ return new Function('return ' + num1 + operator + num2)(); } console.log(calc(2,3,'+')); console.log(calc(5,2,'-')); // 5 // 3 我们可以将返回的函数作为构造器来创建对象
new new Function(); // Object {} 执行函数 函数名加()可以执行一个函数
function foo(){ console.log(123); } foo(); // 123 那如果没有函数名呢
function(){}; // Uncaught SyntaxError: Unexpected token ( 也就是不支持直接这么写,我们需要将以上函数改成一段表达式,将函数进行运算就成表达式了
'' + function(){console.log(5)}; // "function (){console.log(5)}" 那么怎么执行它呢,在函数后面加()
'' + function(){console.log(5)}(); // 5 以上代码不太优雅对吧,我们可以用一个()将它包起来
(function(){console.log(123)}()); // 123 ()也是会进行运算的
(1) // 1 非惰性求值 只要你给函数传递参数它就会进行运算,并不会因为你没有使用它
var a = 10; (function(){}(a++,a++)); console.log(a); // 12 非惰性求值得另外一个例子就是在使用alert时
var a = 1; alert(a+=1,a++); // 2 console.log(a); // 3 第一个输出2是因为alert只接受一个参数,但由于函数是不限制参数个数的并且是非惰性求值所以alert中的第二个参数还是会被运算只是没有被alert使用罢了
函数中的callee、caller callee的意义就在于当我们使用匿名函数时可以去调用函数本身
var a = 0; (function(){ if(a > 3) return; console.log(++a); arguments.callee(); }()); // 1 // 2 // 3 // 4 还有一种情况是当我们重写函数时
var a = 0; function foo(){ if(a > 2)return; console.log(++a); foo = null; arguments.callee(); } foo() // 1 // 2 // 3 caller的意义就在于我们能够知道此函数是被谁调用的
function f1(){ f2(); } function f2(){ console.log(arguments.callee.caller); } f1(); /* function f1(){ f2(); } /*
|