动态执行eval
JavaScript的代码从是运行在一个闭包环境。
JavaScript代码的解释执行过程:
1.在JavaScript中,代码文本是先被解释为语法树,然后按照语法树来执行。
2.在每次执行语法树中的一个函数的实例时,会将语法树中与该函数相关的形式参数、函数局部变量、upvalue以及子函数等信息复制到一个结构中,该结构称为ScriptObject(调用对象)。
3.ScriptObject动态关联到一个闭包,闭包与ScriptObject具有不同的生存周期;
4.按照语法树来执行函数体中的代码,需要访问变量时,先考察ScriptObject中的局部变量等,最后考察upvalue。
这个过程着哦功能,闭包是ScriptObject的执行环境,ScriptObject的数据都存储在闭包。而ScriptObject只是对数据进行标记。
JavaScript的eval()从是将被执行的代码文本视为一个代码块(block),而代码块包含语句组。JavsScript的语句存在返回值,通过最后一条语句返回。(除空语句和控制语句之外)。
如果控制语句,没有返回值哦,在eval的语句执行系统里面
alert(eval('for(var i=0;i<10;i++);'));
返回的是undefined。
如果是赋值语句,没有返回值哦,在eval的语句执行系统里面
alert(eval('i=6; for (var i=0; i<10; i++);;;;'));
返回的是6.
在eval里面,返回的就是最后一条语句。
在eval里面,声明一个对象,
eval('({ value: 1 })')
因为大括号{}在eval的语句执行系统里面会被当作复合语句的标示,等同于if()后面的{}。所以要用运算符()。
eval()的执行环境是当前函数的闭包。
var i = 100;
function myFunc(){
var i = 'test';
eval('i = "hello".');
}
myFunc();
alert(i);
注意点就是,变量作用域会变化。
var i = 100;
function myFunc(ctx){
alert('value is: ' + i);//这里的i调用的是外部变量i
eval(ctx);
alert('value is: ' + i);//这里的i,因为上一条语句的eval里面声明了个i,所以调用上一条语句的
}
myFunc('var i = 10');
动态方法调用call与apply
call与apply功能一样,参数不一样。
什么是call:
function Obj(){this.value="对象!";}
var value="global 变量";
function Fun1(){alert(this.value);}
window.Fun1(); //global 变量
Fun1.call(window); //global 变量
Fun1.call(document.getElementById('myText')); //input text
Fun1.call(new Obj()); //对象!
call的第一个参数,通常是对象,用来替换Fun1方法里面的this。call的第二个,第三个参数等等,就是Fun1方法的参数了。
call的this引用传递例子:
function foo(){
alert(this.name);
}
function MyObject(){
this.name = 'MyObject';
}
MyObject.prototype.doAction = function(){
foo.call(this);
}
var obj3 = new MyObject();
obj3.doAction();
call的传递参数例子:
function clac_area(w, h){
alert(w * h);
}
function Area(){
this.name = 'MyObject';
}
Area.prototype.doCalc = function(v1, v2){
clac_area.call(this,v1, v2);
}
var area = new Area();
area.doCalc(10 ,20);
callee与caller
callee是好东西,是arguments的属性,arguments.callee表示函数对象自身。
一,可以用来获取形式参数和实际参数的个数
function calleeLengthDemo(arg1, arg2) {
alert(arguments.callee.toString());
if (arguments.length == arguments.callee.length) {
window.alert("验证形参和实参长度正确!");
return;
} else {
alert("实参长度:" + arguments.length);
alert("形参长度: " + arguments.callee.length);
}
}
calleeLengthDemo(1);
二,用于匿名函数调用自身,防止全局变量污染咯
函数内部包含了对自身的引用,函数名仅仅是一个变量名,在函数内部调用即相当于调用一个全局变量。
var fn=function(n){
if(n>0) return n+fn(n-1);
return 0;
}
alert(fn(10))
不能很好的体现出是调用自身,这时使用callee会是一个比较好的方法
var fn=(function(n){
if(n>0) return n+arguments.callee(n-1);
return 0;
})(10);
alert(fn)