JavaScript语言精粹2函数对象,函数字面量,调用

函数,用于指定对象的行为。所谓编程,就是将一组需求,分解成函数和数据结构的技能。

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>
原文地址:https://www.cnblogs.com/concentration-web/p/6348034.html