函数,用于指定对象的行为。所谓编程,就是将一组需求,分解成函数和数据结构的技能。
JavaScript中,函数就是对象,是名/值 对的集合。并拥有一个连接到原型对象的隐藏连接。
对象字面量,产生一个对象,连接到Object.prototype,函数对象,连接到Function.prototype.
每个函数对象创建时,会配有一个prototype属性,它的值,是一个拥有constructor属性,且为该函数的对象。
1 var func = function(){ 2 var num; 3 }; 4 var a = func.prototype; 5 console.log(typeof a, a.constructor);//object function
函数可以保存在变量,对象和数组中,可以当参数传递给其他对象,函数可以返回函数,可以返回对象。函数是对象,所以函数也拥有方法!比如apply();
当一个函数被保存为对象的属性时,称它为一个方法。
创建函数,会给该对象一个“调用”的属性,JavaScript调用函数,理解为调用它的“调用”属性。
函数字面量
//创建一个名为add的变量,并用来把求两个数和的函数,赋值给它
var add = function(a,b){
return a+b;
};
函数字面量包括4部分
1关键字function
2函数名,函数可以调用自己的名字,递归。无名是匿名函数anonymous
3形式参数,多个用逗号隔开
4包含在花括号中的一组语句,即函数主体。
函数可以被定义在其他函数之中,一个内部函数,除了可以访问自己的参数和变量,还可以访问,嵌套它的函数的参数和变量。
通过函数字面量创建的函数对象,包含着一个连到,外部上下文的连接,称为闭包closure
调用一个函数,会暂停当前函数的执行,传递控制权和参数给新函数。除了声明时定义的形式参数外(调用时的实参,小于,形参个数,会默认补给undefined,当大于形参个数时,即忽略超出的)每个函数还接收两个附加的参数this和arguments。this在面向对象中非常重要,它取决调用的模式。
JavaScipt有四种调用模式:1方法调用模式2函数调用模式3构造器调用模式4apply调用模式
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>方法,函数调用模式this</title> 6 7 </head> 8 <body> 9 10 </body> 11 </html> 12 <script type="text/javascript"> 13 // var value = 10; 14 var add =function (a,b){ 15 //add(3,4);这样调用函数的时候!this绑定到windows全局对象上 16 var str = "外函数的字符串"; 17 console.log(this); 18 // console.log(this.a,this.b); //this绑定到window,此时window中没有a b属性所以 undefined 19 var speed = function(){ 20 console.log(this);//this绑定在 全局对象window 21 console.log("inner Mthod"); 22 console.log(a,b,str);//直接调用外函数的变量 23 }; 24 speed(); 25 return a+b; 26 }; 27 /*方法调用模式*/ 28 //当一个函数,被保存为,一个对象的属性,称它为一个方法!当一个方法被调用时,this被绑定到该对象上。 29 30 //创建一个对象,它有一个value属性 increment方法 31 //incrment方法接收一个可选的参数,如果不是数字,就使用默认设定1 32 var myObject = { 33 value: 0, 34 increment: function (inc){ 35 this.value += typeof inc === 'number' ? inc : 1; 36 console.log(this); 37 } 38 }; 39 40 myObject.increment(); 41 document.writeln(myObject.value);//没传参数,即1 42 myObject.increment(3); 43 document.writeln(myObject.value);//此时value已经是1,1+3 = 4 44 //方法可以使 this访问自己,所属的对象,所以它能,从对象中取值或对 对象进行修改 45 //this理解为是个,绑定!this到对象的绑定发生在,调用的时候!!! very late binding 使函数对this高度复用 46 /*函数调用模式*/ 47 console.log(add(3,4)); //add(a,b)是window对象的方法,this此时绑定,全局对象window 48 console.log(window.add(3,4)); 49 50 51 //为myObject添加一个方法test_double,且该方法中有一个内部函数test_helper 52 myObject.test_double = function(){ 53 // var that = this; 54 console.log(this);//此时,以myObject.test_double()方法调用时,this绑定到当前调用此方法Object 属性value是4 55 var test_helper = function(){ 56 console.log(this,this.value);//此时方法中的内部函数,test_helper函数不是对象myObject的属性!! 57 //test_helper是以函数调用模式,this绑定在全局对象!window! 58 this.value = add(this.value,this.value);//undefiend,假设,有个全局变量var value =10,则此处值为add(10,10); 59 console.log(this.value);//NaN无法计算的值,假设有全局变量var value =10,则此处值为20 60 } 61 test_helper(); 62 }; 63 // myObject.test_double(); 64 // document.writeln(myObject.value);//内部的函数没有修改myObject的属性value,此处为4 65 //在对象myObject中的一个test_double方法,中的一个内部函数test_helper,中this,是绑定在全局对象window,内部函数this不能访问对象myObject的属性value。---文中的"不能共享,该方法对 对象的访问权"! 66 67 //解决对象myObject方法double中 内部函数help,访问对象myObject属性!只需要在方法double中,赋值this给一个方法的变量that 68 //为myObject添加一个方法 double,且方法中有个内部函数 help 69 myObject.double = function (){ 70 var that = this; 71 var help = function(){ 72 that.value = add(that.value,that.value);//当前myObjec的value是4 73 } 74 help(); 75 }; 76 myObject.double();//函数double作为对象属性,即是对象的方法调用模式 77 document.writeln(myObject.value); 78 79 80 </script>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>构造器函数Apply,this</title> 6 </head> 7 <body> 8 9 </body> 10 </html> 11 <script type="text/javascript"> 12 //构造器调用模式 13 /* 14 JavaScript是一门基于原型继承的语言!对象可以从其他对象继承属性!JavaScript是无类型的! 15 */ 16 //创建一个名为 Quo的构造器函数,它构造带有status属性的对象 17 //一个函数,创建的目的就是为了用 new前缀来调用,它被称为构造器函数!约定保存在一个大写的变量中! 18 var Quo = function(string){ 19 console.log(this); 20 this.status = string; 21 }; 22 //给对象所有实例一个公共方法 23 Quo.prototype.get_status = function(){ 24 console.log(this); 25 return this.status; 26 }; 27 28 Quo("Right?");//此时,函数不是对象的属性,即不是对象的方法,以函数调用模式,此时,this绑定到window 29 //当用 new调用,创建了一个对象,this即绑定到新的对象!新的对象即有status属性 30 31 var myQuo = new Quo("confused");//是用 new前缀调用函数,新建一个对象的实例,一个连接到,该函数的prototype成员,的新对象,且this绑定在该对象上 32 console.log(myQuo.status); 33 document.writeln(myQuo.get_status()); 34 //不推荐这种形式的构造器函数,会有更好的代替方式 35 36 37 //Apply调用模式 38 39 /* 40 JavaScript是函数式面向对象的语言,函数是对象,所以函数可以拥有方法 41 42 */ 43 44 45 46 //window全局变量 47 window.a = 12; // 即 var a = 12; 48 var add = function(a,b){ 49 console.log(a,b);//传人的实参 50 console.log(this.a,this.b);//window的全局变量中的 a 和 b,没有定义,即undefined 51 return a+b+"/ "+(this.a+this.b); 52 }; 53 //创建一个包含两个数字的数组 54 var array = [3,4]; 55 //apply方法,接收两个参数,一个是绑定this的值,第二个是数组参数,此时的参数是要应用的函数所带的参数! 56 //apply方法,构建,一个参数数组传递给调用函数 57 console.log(add.apply(null,array));//第一个参数,this的绑定值设为null,是全局变量window 58 //add.apply(null,array); 即 add的this.a 是 window.a ,但没有定义b,所以this.a+this.b无法计算是 NaN 59 60 61 //---创建一个reObject对象定义 62 var reObject ={ 63 a: 2, 64 b: 5, 65 }; 66 //此处即是reObject对象应用了add()方法,this绑定的是reObject,即this.a 是reObject的a,如果没定义即,undefined 67 console.log(add.apply(reObject,[6,9])); 68 69 70 //创建一个有status成员的对象 71 var statusObject = { 72 status: 'A-OK' 73 }; 74 //statusObject没有 继承 Quo.prototype! 但是可以调用,get_status(),尽管statusObject没有get_status一个方法 75 //相当于,statusOject应用了get_status函数,get_status()是没有定义参数 76 var status = Quo.prototype.get_status.apply(statusObject); 77 //this绑定(指向)statusObject,则应用的方法 get_status中的this.status即是 statusObject的 status! 78 console.log(status); 79 80 81 </script>