上一篇中讲了有关prototype chain(原型链)的相关知识。在这个章节中,主要讲内置的参数,函数的用法。因为在学习《JavaScript设计模式》中很多次出现,如果只是浅显的了解,学习的过程中会有很多感觉很吃力的时候,所以,也花了些功夫从网上和书本上找了一些材料学习,算是有了点了解。从网上搜集的材料连接放在上一篇原型链的开头处,需要的同学自己去找吧。
Arguments
在讲arguments前,先明确一点:arguments是一个对象。
-
function Sub(){
-
}
-
console.log(typeof Sub.arguments)
结果输出:object
Arguments是该对象正在执行的杆数和调用它的函数的参数。拿个例子来解释吧。
-
function test(){
-
this.testArgument = function(){
-
for(var i=0;i<arguments.length;i++){
-
console.log("Argument "+i + ":"+ arguments[i]);
-
}
-
console.log("Argument length: "+ arguments.length);
-
}
-
}
-
var tmp = new test();
-
tmp.testArgument("df","sdf");
结果输出:
上述代码出现了很有意思的地方。我们没有定义testArgument(String str1,String str2)的方法,只定义了没有参数的testArgument()方法。原来javascript会自动忽略多出来的参数。而这些参数会保存在arguments对象中。记住,arguments对象的索引是从0开始滴。
With
这个关键子就是方便书写的意思。和java中的静态引入有点像,看例子:
-
function testWith(){
-
this.a = 6;
-
this.b = "with";
-
}
-
var tmp = new testWith();
-
with(tmp){
-
console.log(a);
-
console.log(b);
-
}
从上面代码中可以看到,使用with之后,在代码体中不用写tmp.a,而直接使用a即可。是不是和java中的静态引入很像!
Caller
这个函数的意思就是,返回一个函数的引用,该函数调用了这个函数。可能光听解释不太明白,看代码:
-
function callerDemo(){
-
if(callerDemo.caller){
-
var a = callerDemo.caller.toString();
-
console.log(a);
-
}else{
-
console.log("this is a top function");
-
}
-
}
-
(function call(){
-
callerDemo();
-
})();
输出结果:
在代码中第三行,我们调用了toString方法,也就是说callerDemo.caller返回的是call()这个函数的引用。
可能有些同学看不明白()();的用法。这里简单解释一下,这里可以吧第一个()看作成一个匿名函数,暂且记作xx,第二个括号就是调用这个匿名函数,也就相当于xx();
Callee
这个函数有点不好理解。Callee是arguments的一个属性,这个属性返回的是这个函数的自身。Callee有一个属性length,为函数形参的长度。
形参:就是命名函数时定义的参数;实参:实际调用函数时的参数个数。直接看例子
-
//用于验证参数
-
function calleeLengthDemo(arg1, arg2) {
-
if (arguments.length==arguments.callee.length) {
-
console.info(typeof arguments.callee);
-
console.info(arguments.callee === calleeLengthDemo);
-
console.log("pass!");
-
return;
-
} else {
-
console.log("actual:" +arguments.length); //实参的数目
-
console.log("defined: " +arguments.callee.length); //形参的数目
-
}
-
}
-
(function(){
-
calleeLengthDemo(11,22);
-
calleeLengthDemo(11,22,33,44);
-
})();
-
//递归计算
-
var sum = function(n){
-
if (n <= 0)
-
return 0;
-
else
-
return n + arguments.callee(n - 1)
-
}
-
console.log(sum(10));
这个例子分为两部分,第一部分1~16是说明arguments.callee.length代表的是什么,以及arguments.callee返回的就是该对象本身;第二部分17~24使用了一个递归的例子,说明这个函数的具体用法。
输出结果:
从结果中可以看出,callee的用法。返回结果true证明arguments.callee返回的就是其函数本身。arguments.callee的类型也是function类型。
Call,apply
-
call([thisObj[,arg1[,arg2[,[,.argN]]]]])
光看这个可能看的不明白。上面call的用法就是:thisObj是必填项,arg是可选项,每一个参数必须是使用逗号分隔。thisObj如果填写null,将用Globe作用于指定。
这个函数的作用是什么呢?先看代码:
-
function Base(){
-
this.a = 5;
-
this.b = "haha";
-
}
-
-
(function Sub(){
-
this.c = "Hello";
-
Base.call(this);
-
console.log(this.a + " ||" +this.b + "||" + this.c);
-
})();
输出结果:5 ||haha||Hello
Call函数的作用就是,将一个函数的作用域叠加于另一个函数上,在上述代码中Base.call(this)就是把Base的作用域叠加到this的作用于。所以在代码中第8行,this.a与this.b就只带的是Base.a与Base.b,而this.c输出Hello证明这个代码的作用是叠加关系
那既然是叠加,如果Base和Sub同时有相同的属性,该怎么执行呢?
-
function Base(){
-
this.a = 5;
-
this.b = "haha";
-
this.c = 'Hello World';
-
}
-
-
(function Sub(){
-
this.c = "Hello";
-
Base.call(this);
-
//this.c = "Hello";
-
console.log(this.a + " ||" +this.b + "||" + this.c);//结果输出5||haha||Hello World
-
})();
结果输出:5||haha||Hello World
上面代码中可以看到,这个叠加也有一个先后顺序。Base.call(this)的作用相当于把Base中的代码复制到这块:
-
function Base(){
-
this.a = 5;
-
this.b = "haha";
-
this.c = 'Hello World';
-
}
-
-
(function Sub(){
-
this.c = "Hello";
-
//Base.call(this)开始
-
this.a = 5;
-
this.b = "haha";
-
this.c = 'Hello World';
-
//Base.call(this)结束
-
console.log(this.a + " ||" +this.b + "||" + this.c);
-
})();
所以this.c='Hello World'这个语句吧第8行中的this.c='Hello'覆盖掉了。至于this.c最终等于什么,就看Base.call(this)调用的位置了。
Apply
-
apply([thisObj[,argArray]])
这个函数的作用同call是一样的,只不过argArray参数是一个数组形式的,既可以直接把arguments当作参数传递,如果没有就有因个空数组代替
这里跟查的资料不一样,资料上说argArray是必选项,不然会抛出TypeError错误,但是我在node和IE浏览器中验证,这个argArray也是一个可选项
因为作用是相同的,所以在这里就不再重复的写一下代码了。下面介绍这里面的参数是怎么用的:
-
function par(name,age){
-
this.parName = name;
-
this.parAge = age;
-
}
-
function child(chname,parname,parAge){
-
this.chName=chname;
-
par.apply(this,[parname,parAge]);
-
};
-
-
var child=new child("john","Mr john","50");
-
console.log(child.parName+";"+child.chName+ ";"+child.parAge);
结果输出:Mr john;john;50
上面代码中,定义了一个par函数,里面有parName和parAge,在代码第七行中使用了par.apply(this,[parname,parAge]);把parname,parAge参数传递给par函数。进行初始化。
当然也可以把arguments当作参数传递。Call中的参数用法和apply类似。不重复了。
eval
eval函数接受一个参数s,如果s不是一个字符串,直接返回s;否则执行s语句。如果s语句执行结果是一个值,则返回该值,否则返回undefined。
-
var testEval_int = 5;
-
var testEval_obj = {a:2};
-
console.log(eval(testEval_int));
-
-
var testEval_str = "(function tmp(){this.a =5;this.b = 'haha';console.log(a + ':' + b);})();";
-
eval(testEval_str);
输出结果:5:haha