- 方法调用模式
- 函数调用模式
- 构造器调用模式
- apply/call调用模式
具体细节参见我之前在segmentfault上的回答 https://segmentfault.com/q/1010000003902369/a-1020000003902506
在ES5 严格模式下,对这两个属性进行读写会产生类型错误
- callee是指当前正在执行的函数
- caller是指调用当前正在执行的函数的函数
通过caller属性可以访问调用栈,通过callee可以递归的调用自己
function a(){
console.log("inner a callee: ", arguments.callee.name, " caller: " + a.caller);
}
function b(){
console.log("inner b callee", arguments.callee.name, " caller: " + b.caller);
a();
}
b()
这个应该是所有人学习JavaScript最头疼的概念了 函数体内部的变量可以保持在函数作用域内。 关于这块的理解,引用公司大神的一篇文章 kuitos/kuitos.github.io#18
p185-p187 4 个例子,很好的利用了闭包
利用length属性判断形参和实参个数
function check(args){
var actual = args.length;
var expected = args.callee.length;
if(actual !== expected){
throw Error("Expected " + expected + "args; got " + actual);
}
}
function f(x, y ,z){
check(arguments);
return x + y + z;
}
prototype 属性
call 方法 和 apply 方法
//有点面向切面变成的意思
function trace(o, m){
var original = o[m];
o[m] = function(){
console.log(new Date, "Entering: ", m);
var result = orignial.apply(this, arguments);
console.log(new Date, "Exiting: ", m);
return result;
}
}
function before(o, m, fun){
var original = o[m];
o[m] = function(){
var args = Array.prototype.slice.call(arguments);
var newArgs = fun.apply(this, args);
var result = orignial.apply(this, newArgs);
return result;
}
}
function after(o, m, fun){
var original = o[m];
o[m] = function(){
var result = orignial.apply(this, arguments);
var newResult = fun.apply(this, [result]);
return newResult;
}
}
bind方法 柯里化
var sum = function(x, y){ return x+y;};
var succ = sum.bind(null, 1);
succ(2); //3
function f(y, z){return this.x + y + z;}
var g = f.bind({x:1}, 2);
g(3); //6
toString方法 函数的toString方法可以将函数中的注释 显示出来,非常的有意思,我们可以用它来模拟ES6 多行字符串 https://github.com/sindresorhus/multiline
Function() 构造函数
- Function构造函数允许JavaScript在运行时动态的创建并编译函数
- 每次调用 Function()构造函数都会解析函数体,并创建新的函数对象。
- 最后一点,也是关于Function()构造函数非常重要的一点,就是它所创建的函数不是使用词法作用域,相反,函数体代码编译总会在顶层函数执行