JS中的函数不一样于其余的语言,每一个函数都是做为一个对象被维护和运行的。经过函数对象的性质,能够将一个函数赋值给一个变量或者将函数做为参数传递。编程
用法:数组
function Func1(...){......};app
var Func2 = function(...){......};函数
var Func3 = function Func4(...){......};this
var Func5 = new Function();spa
**函数对象!!prototype
能够用function关键字定义一个函数,并为每一个函数指定一个函数名,经过函数名来进行调用。在JS解释执行时,函数都是被维护为一个对象,这就是函数对象(function object)。设计
函数对象与其余用户所定义的对象有着本质的区别,这一类对象称之为内部对象,例如Date,Array,String 都属于内部对象。这些内置对象的构造器是由JS自己所定位的:经过执行 new Array() 这样的语句返回一个对象,JS内部有一套机制来初始化返回的对象,而不是由用户来指定对象的构造方式。指针
在JS中,函数对象对应的类型是Function,(数组对应Array,日期对应Date),能够经过 new Function() 来建立一个函数对象,也能够经过 function 关键字来建立一个对象。 code
var myArray = []; var myArray = new Array(); function myFunction1(a,b){ return a+b; }; var myFunction = new Function('a','b','return a+b');
以上代码,经过和构造数组对象语句的比较,能够清楚的看到函数对象本质。第一种方式,在解释器内部,当遇到这种语法时,就会自动构造一个Function对象,将函数做为一个内部的对象来存储和运行。(一个函数对象名称(函数变量)和一个普通变量名称具备一样的规范,均可以经过变量名来引用这个变量,可是函数变量名后面能够跟上括号和参数列表来进行函数的调用。var myFunction = new Function("a,b","return a+b"),这个方式可读性较差)。
** var funcName = new Function(P1,P2,P3...Pn,body) 参数的类型都是字符串,P1到Pn表示所建立函数的参数名称列表,body表示所建立函数的函数体语句。
**注意,P1到Pn是参数名称的列表,即P1不只能表明一个参数,它也能够是一个逗号隔开的参数列表。
**JS导入Function类型并提供 new Function() 这样的语法是由于函数对象添加属性和方法就必须借助于Function这个类型。
**函数的本质是一个内部对象!由JS解释器决定其运行方式。**
**注意:直接在函数声明后面加上括号就表示建立完成后当即进行函数调用。返回一个number类型
var myfunc2= function(a,b){ return a+b; }(100,200);//优先级决定的,‘(’优先级大于‘=’,因此myfunc2是一个变量,而不是一个函数 alert(typeof(myfunc2));//number alert(myfunc2); alert(myfunc2(10,20));//报错,myfunc2不是一个函数!
**可是不直接调用,返回的是一个function类型
var Myfunc2=function(a,b){ return a+b; } alert(typeof(Myfunc2));//function alert(Myfunc2(1,2));
**注意有名函数和无名函数!
**区别:对于有名函数,它能够出如今调用以后再定义;而对于无名函数,必须在调用以前定义。
**由于JS是一门解释型语言,但它会在函数调用时,检查整个代码中是否存在相应的函数定义。只有经过function FuncName(...){...} 才有效,而不是无名函数。
function Myfunc1(a,b){//有名函数 return a+b; } alert(Myfunc2(1,2));//报错 var Myfunc2=function(a,b){//无名函数 return a+b; } alert(typeof(Myfunc2));//function
除了函数对象,还有不少内部对象,好比:Object,Array,Date.....这些都表示一个类型,能够经过 new 操做符返回一个对象,然而函数对象和其余对象不一样,当用typeof获得一个函数对象的类型时,它仍然会返回字符串“function”,而typeof一个数组对象或其余的对象时,它会返回字符串“Object”。
//function alert(typeof(Function)); alert(typeof(new Function())); alert(typeof(Array)); alert(typeof(Object)); //object alert(typeof(new Array())); alert(typeof(new Date())); alert(typeof(new Object())); if(typeof(tt)=="function"){//判断是function类型在运行,一般的作法 arg(); }
**new 一个Function,其实是返回一个函数。这于其余的对象有很大的不一样。其余的类型Array,Object等都会经过 new 操做符返回一个普通对象(Object)。
**尽管函数自己也是一个对象,但它与普通的对象仍是有区别的,由于它同时也是对象构造器,也就是说,能够new 一个函数来返回一个对象,全部typeof返回‘function’的对象都是函数对象,也叫构造器(constructor)。全部的构造器都是对象,但不是全部的对象都是构造器。
**Function类型的做用,就是能够给函数对象自己定义一些方法和属性,借助于函数的prototype对象,能够方便地修改和扩充Function类型的定义。
**Function是全部函数对象的基础,而Object则是全部对象(包括函数对象)的基础。在JS中,任何一个对象都是Object的实例。所以,能够修改Object这个类型来让全部的对象具备一些通用的属性和方法,修改Object类型是经过prototype来完成的。
Function.prototype.Methods=function(){ alert('function'); } function tt(){ alert('tt'); } tt.Methods(); tt.Methods.Methods();//递归的定义。Methods自己也是一个函数,因此它一样具备函数对象的属性和方法,
//全部对Function类型的方法扩充都具备这样的递归性质。 Object.prototype.getType=function(){ return typeof(this); } var array1=new Array(); function func1(a,b){ return a+b; } alert(array1.getType()); alert(func1.getType());
函数对象的本质:就是一个内部对象!Function类型的对象,类型仍是Function。
**每一个函数都被表示为一个特殊的对象,能够方便地将其赋值一个变量,再经过这个变量名进行函数调用。做为一个变量,它能够以参数的形式传递给另外一个函数。
function func1(thefunc){ if(typeof(thefunc)=='function'){// thefunc(); }else{ alert(typeof(thefunc)); } } function func2(){ return '123'; } function func3(a,b){ var result =a+b; alert(result); } function func4(a,b,c){ var result =a+b+c; alert(a+b+c); } func1(func2());//执行结果传递过去 func1(func2);//func2做为一个对象传递给func1的形参thefunc,再由func1内部进行thefunc的调用。 //事实上,将函数做为参数传递,或者是将函数赋值给其余变量是全部事件机制的基础。 //将func3传递给func1; //var t=new func3(1,2); //func1(func3); var t1 = new func3(1,2); alert(typeof(t1));
当进行函数调用时,除了指定的参数外,还建立了一个隐含的对象--arguments,arguments是一个相似数组但不是数组的对象,说它相似是由于它具备数组同样的访问性质,能够用arguments[index]这样的语法取值,拥有数组长度属性length。arguments对象存储的是实际传递给函数的参数,而不局限于函数声明所定义的参数列表,例如:
function Myfunc(a,b){ alert(a); alert(b); for (var i=0;i<arguments.length;i++) { alert(arguments[i]); } } Myfunc(1,2)//显示:1,2,1,2 Myfunc(1,2,3)//显示:1,2,1,2,3
**所以,在定义函数的时候,即便不指定参数列表,仍然能够经过arguments引用到所得到的参数,这给编程带来了很大的灵活性。
**arguments对象的另外一个属性callee,它表示对函数对象自己的引用,这有利于实现无名函数的递归或者保证函数的封装性。
var sum =function(n){ if(1==n){ return 1; }else{ return n+sum(n-1);//递归的调用 } } alert(sum(100)); //arguments.callee 表示对函数对象自己的引用,有利于实现无名参数的递归或者保证函数的封装性 var sum2 =function(n){ if(1==n){ return 1; }else{ return n+arguments.callee(n-1);//arguments.callee,递归的调用 } } alert(sum2(100));
**callee属性并非arguments不一样于数组对象的惟一特征,如下代码:
Array.prototype.p1 = 1;//给因此数组对象添加属性p1,初始化值为1. alert(new Array().p1);//1 function func(){ alert(arguments.p1); } func();//undefined 说明p1不是arguments的属性
**arguments的length的模拟实现方法的重载
//arguments能够实现方法的重载! function myFunc(){ var result=0; if(arguments.length==2){ result =arguments[0]+arguments[1]; }else if(arguments.length==3){ result=arguments[0]+arguments[1]+arguments[2]; } /* for(var i=0;i<arguments.length;i++){ result+=arguments[i]; } */ return result; } alert(myFunc(1,2,3));//6 alert(myFunc(1,2));//3
JS对函数对象定义了两个方法:apply和call,它们的做用都是将函数绑定到另一个对象上去运行,二者仅在定义参数的方式有所区别:
Function.prototype.apply(thisArg,argArray);
Function.prototype.call(thisArg,"arg1","arg2"...)
从函数原型能够看到,第一个参数都被取名为thisArg,即全部函数内部的this指针都会被赋值为thisArg,这就实现了将函数做为另一个对象的方法运行的目的.
//apply call function func1(){ this.p="func1-"; this.A=function(arg){ alert(this.p+arg+'<func1>'); }; }; function func2(){ this.p="func2-"; this.B=function(arg){ alert(this.p+arg+"<func2>"); } } var obj1=new func1(); var obj2=new func2(); //obj1.A("byA");//正常调用 //obj2.B("byB");//正常调用 obj1.A.apply(obj2,["byA"]); obj2.B.apply(obj1,["byB"]); obj1.A.call(obj2,"byA"); obj2.B.call(obj1,"byB"); //能够看出,obj1的方法A被绑定到obj2运行后,整个函数A的运行环境就转移到了obj2,即this指针指向了obj2. //一样,obj2的函数B也能够绑定obj1运行,整个函数B的运行环境就转移到了obj1,即this指针指向了obj1.
函数对象的属性length,它表示函数定义时所指定参数的个数,而非调用时实际传递的参数个数
//函数对象的属性length,它表示函数定义时所指定参数的个数,而非调用时实际传递的参数个数 function sum(a,b,c) { return a + b+c; } alert(sum.length);//3 var t1=sum; alert(t1);
this指针是面向对象程序设计中的一项重要概念,塔表示当前运行的对象.在实现对象的方法时,可使用this指针来得到该对象的自身的引用.
和其余语言不一样,JS中的this指针是一个动态的变量,一个方法内的this指针并非始终指向定义该方法的对象的,它能够是动态的!
var obj1=new Object(); var obj2=new Object(); obj1.p=1; obj2.p=2; obj1.getP=function(){ alert(this.p); } obj1.getP();//1 obj2.getP=obj1.getP;//函数对象赋值给函数对象 obj2.getP();//2 //因而可知,getP函数仅定义了一次,在不一样的场合运行,显示了不一样的运行结果.这是由this指针的变化所决定的. //在obj1的getP方法中,this就指向了obj1对象,而在obj2的getP方法中,this就指向了obj2对象,并经过this指针引用到了两个对象都具备的属性p
**JS中的this指针是一个动态变化的变量,它表面了当前运行该函数的对象.由this指针的性质,也能够更好的理解JS中对象的本质:一个对象就是由一个或多个属性(方法)组成的集合.每一个集合元素不是仅能属于一个集合,而是能够动态的属于多个集合.这样,一个方法(集合元素)由谁调用,this指针就指向谁!
**实际上,apply方法和call方法都是经过强制改变this指针的值来实现的,使this指针指向参数所指定的对象,从而达到将一个对象的方法做为另外一个对象的方法运行.
命名空间的概念(重要)
/* * 每一个对象集合的元素(即属性或方法)也是一个独立的部分,全局函数和做为一个对象方法定义的函数之间没有任何区别. * 由于能够把全局函数和变量看做为window对象的方法和属性.也可使用new操做符来操做一个对象的方法来返回一个对象, * 这样一个对象的方法也就能够定义为类的形式,其中的this指针则会指向新建立的对象.这时对象名能够起到一个命名空间的 * 做用,这是使用js进行面向对象程序设计的一个技巧. * */ var namespace1 = new Object();//这里就能够把namespace1当作一个命名空间 namespace1.class1 = function() {//namespace1命名空间下面的类class1 //初始化对象代码 } var obj1=new namespace1.class1();//