此文的目的是分析函数的四种调用形式,弄清楚函数中this的意义,明确构造函对象的过程,学会使用上下文调用函数。javascript
在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而非像C#或 其余描述性语言那样仅仅做为一个模块来使用. 函数有四种调用模式,分别是:函数调用形式、方法调用形式、构造器形式、以及apply形式. 这里全部的调用模式中,最主要的区别在于关键字 this 的意义. 下面分别介绍这个几种调用形式.java
1、函数调用形式数组
函数调用形式是最多见的形式,也是最好理解的形式. 所谓函数形式就是通常声明函数 后直接调用便是. 例如:浏览器
1 //声明一个函数,而且调用 2 function func(){ 3 alert('Hello World!!'); 4 } 5 func();
或者app
1 //使用函数的Lambda表达式定义函数 2 var func = function(){ 3 alert("Hello World!!"); 4 } 5 func();
这两段代码都会弹出一个对话框,显示字符串中的文字. 这个就是函数调用。函数
能够发现函数调用很简单,就是平时学习的同样. 这里的关键是,在函数调用模式中, 函数里的 this 关键字指全局对象,若是在浏览器中就是 window 对象. 例如:学习
1 var func = function(){ 2 alert(this); 3 } 4 func();
此时,会弹出对话框,打印出 [object Window]this
2、方法调用模式spa
函数调用模式很简单,是最基本的调用方式. 可是一样的是函数,将其赋值给一个对象的成员之后,就不同了. 将函数赋值给对象的成员后,那么这个就不在称为函数,而code
应该叫作方法. 例如:
1 // 定义一个函数 2 var func = function() { 3 alert("我是一个函数么?"); 4 }; 5 // 将其赋值给一个对象 6 var o = {}; 7 o.fn = func; // 注意这里不要加圆括号 8 // 调用 9 o.fn();
此时,o.fn 则是方法,不是函数了. 实际上 fn 的方法体与 func 是如出一辙的,可是这里有个微妙的不一样. 看下面的代码:
1 // 接上面的代码 2 alert(o.fn === func);
打印结果是 true ,这个代表两个函数是同样的东西. 可是修改一下函数的代码:
1 // 修改函数体 2 var func = function() { 3 alert(this); 4 }; 5 var o = {}; 6 o.fn = func; 7 // 比较 8 alert(o.fn === func); 9 // 调用 10 func(); 11 o.fn();
这里的运行结果是,两个函数是相同的,所以打印结果是 true. 可是因为两个函数的调用是不同的,func 的调用,打印的是 [object Window],而 o.fn 的打印结果是 [object Object].
这里即是函数调用与方法调用的区别. 函数调用中,this 专指全局对象 window,而 在方法中 this 专指当前对象. 即 o.fn 中的 this 指的就是对象 o.
3、构造器调用模式
一样是函数,在单纯的函数模式下,this 表示 window;在对象方法模式下,this 指的是当前对象. 除了这两种状况,javascript 中函数还能够是构造器. 将函数做为构造器来使用的语法就是在函数调用前面加上一个 new 关键字. 如代码:
1 // 定义一个构造函数 2 var Person = function() { 3 this.name = "传智播客"; 4 this.sayHello = function() { 5 alert("你好,这里是" + this.name); 6 }; 7 }; 8 // 调用构造器,建立对象 9 var p = new Person(); 10 // 使用对象 11 p.sayHello();
上面的案例首先建立一个构造函数Person,而后使用构造函数建立对象p. 这里使用 new 语法. 而后在使用对象调用sayHello()方法. 这个使用构造函数建立对象的案例比较简单. 从案例能够看到,此时 this 指的是对象自己.
除了上面简单的使用之外,函数做为构造器还有几个变化. 分别为:
一、 全部须要由对象使用的属性,必须使用 this 引导;
二、 函数的 return 语句意义被改写,若是返回非对象,就返回this;
3.1 构造器中的 this
咱们须要分析建立对象的过程,方能知道 this 的意义. 以下面代码:
1 var Person = function() { 2 this.name = "Hello cc!!"; 3 }; 4 var p = new Person();
这里首先定义了函数 Person,下面分析一下整个执行:
一、 程序在执行到这一句的时候,不会执行函数体,所以javascript 的解释器并不知道这个函数的内容。
二、 接下来执行 new 关键字,建立对象,解释器开辟内存,获得对象的引用,将新对象的引用交给函数。
三、 紧接着执行函数,将传过来的对象引用交给 this 也就是说,在构造方法中,this 就是刚刚被 new 建立出来的对象.
四、 而后为 this 添加成员,也就是为对象添加成员.
五、 最后函数结束,返回 this, 将 this 交给左边的变量.
分析过构造函中数的执行之后,能够获得,构造函数的 this 就是当前对象.
3.2 构造器中的 return
在构造函数中 return 的意义发生了变化,首先若是在构造函数中,若是返回的是一个对 象,那么就保留原意. 若是返回的是非对象,好比数字、布尔和字符串,那么就返回 this,如
果没有 return 语句,那么也返回 this. 看下面代码:
1 // 返回一个对象的 return 2 var ctr = function() { 3 this.name = "cc"; 4 return { 5 name:"xx" 6 }; 7 }; 8 // 建立对象 9 var p = new ctr(); 10 // 访问name属性 11 alert(p.name);
执行代码,这里打印的结果是"xx". 由于构造方法中返回的是一个对象,那么保留 return的意义,返回内容为 return 后面的对象. 再看下面代码:
1 // 定义返回非对象数据的构造器 2 var ctr = function() { 3 this.name = "cc"; 4 return "xx"; 5 }; 6 // 建立对象 7 var p = new ctr(); 8 // 使用 9 alert(p); 10 alert(p.name);
代码运行结果是,先弹窗打印[object Object],而后打印"cc". 由于这里 return 的是一个字符串,属于基本类型,那么这里的 return 语句无效,返回的是 this 对象. 所以第一个打印的 是[object Object]而第二个不会打印 undefined.
4、apply调用模式
除了上述三种调用模式之外,函数做为对象还有 apply 方法与 call 方法可使用,这即是 第四种调用模式,我称其为 apply 模式.
首先介绍 apply 模式,首先这里 apply 模式既能够像函数同样使用,也能够像方法同样使用 能够说是一个灵活的使用方法. 首先看看语法: 函数名.apply(对象, 参数数组);
这里看语法比较晦涩,仍是使用案例来讲明:
一、 新建两个 js 文件,分别为"js1.js"与"js2.js";
二、 添加代码
三、 分别运行着两段代码,能够发现第一个文件中的 name 属性已经加载到全局对象 window 中;而第二个文件中的 name 属性是在传入的对象 o 中. 即第一个至关于函数调用,第二个至关于方法调用.
1 // js1.js 文件中 2 var func1 = function() { 3 this.name = "Hello cc!!"; 4 }; 5 func1.apply(null); 6 alert(name); 7 // js2.js 文件 8 var func2 = function() { 9 this.name = "Hello xx!!"; 10 }; 11 var o = {}; 12 func2.apply(o); 13 alert(o.name);
这里的参数是方法自己所带的参数,可是须要用数组的形式存储在. 好比代码:
1 // 一个数组的例子 2 var arr1 = [1,2,3,[4,5],[6,7,8]]; 3 // 将其展开 4 var arr2 = arr1.conact.apply([], arr1);
而后介绍一下 call 模式. call 模式与 apply 模式最大的不一样在于 call 中的参数不用数组. 看下面代码就清楚了:
1 // 定义方法 2 var func = function(name, age, sex) { 3 this.name = name; 4 this.age = age; 5 this.sex = sex; 6 }; 7 // 建立对象 8 var o = {}; 9 // 给对象添加成员 10 // apply 模式 11 var p1 = func.apply(o, ["xx", 25, "男"]); 12 // call 模式 13 var p2 = func.call(o, "xx", 25, "男");
上面的代码,apply 模式与 call 模式的结果是同样的.
实际上,使用 apply 模式和 call 模式,能够任意的操做控制 this 的意义,在函数 js 的设 计模式中使用普遍. 简单小结一下,js 中的函数调用有四种模式,分别是:函数式、方法式、构造
器式和 apply 式. 而这些模式中,this 的含义分别为:在函数中 this 是全局对象 window,在方法中 this 指当前对象,在构造函数中 this 是被建立的对象,在 apply 模式中 this 能够随意的
指定. 在 apply 模式中若是使用 null,就是函数模式,若是使用对象,就是方法模式.