JavaScript函数的各种调用模式

函数是JavaScript世界里的第一公民,换句话来说,就是我们如果可以精通JavaScript函数的使用,那么对JavaScript的运用可以更游刃有余了。熟悉JavaScript的人应该都知道,同样的函数,以不同的方式调用的话,受影响最大的应该是  this 。下面我们来说说JavaScript函数的各种调用模式。

一、普通函数的调用模式

  所谓普通函数的调用模式,也是JavaScript函数的最简单的一种调用模式,直接就是函数名后接一个  ()  实现调用,看下面代码:

function func(){
    console.log(this === window);  //true
}
func();

  上面代码,我们用function关键字声明了一个 func 函数,并且在函数体内打印 this===window,然后我们直接调用函数func,我们可以看到控制台是直接打印出 true ,也就是说,函数的这种普通调用模式,函数体内的  this  是指向全局环境 window 的。不清楚这点的同学,可以能会遇到这样的一个bug:

var color = ‘gg‘;
var obj = {
    color : ‘red‘,
    show : function(){
        function func1(){
            console.log(this.color);  //gg
        }
        func1();
    }
}
obj.show(); 

  我们在全局环境下声明了一个变量 color 和一个对象 obj ,在对象 obj 里面我们还声明了一个 color 属性 为 ‘red‘,一个 show 方法。而且在 show 方法里面呢,我们还声明了一个函数 func1 并且调用了 func1,func1 的作用是打印 this.color。最后我们运行代码  obj.show();   调用obj里面的show方法。不清楚函数的普通调用模式的特点的同学可能会认为此时在控制台答应出来的会是  ‘red‘ 。实际上此时在控制台答应出来的应该是  gg  。因为函数  func1  的调用模式是 普通函数调用模式(即使它是在  obj  的  show  方法里面调用的),所以此时函数体内的  this  是指向 全局环境window 的,所以就打印了全局环境下的变量  color 。

  可能有些同学会问:如果我们希望  func1  函数打印出来的是 ‘red‘ 呢,应该怎么改?其实很简单,因为  obj.color  才是 ‘red‘ ,所以我们只需要把  指向  obj  的  this 引入到函数 func1  里面就行了:

var color = ‘gg‘;
var obj = {
    color : ‘red‘,
    show : function(){
        var that = this;
        function func1(){
            console.log(that.color);  //red
        }
        func1();
    }
}
obj.show();

  在上面的代码中,因为  show  里面的   this  指向   obj   的,所以我们在  show  里面声明一个变量  that = this;用来把指向  obj  的  this  引入到  func1 中,然后再把 func1 函数体内的  this.color  改为  that.color ,此时在控制台打印出来的就是我们想要的 ‘red‘ 了。

  可能现在又有同学会问:为什么   show   里面的  this  是指向  obj 的呢?这就是我们要说的JavaScript函数的第二种调用模式:方法调用模式

二、方法调用模式

  方法调用模式,简单来说就是把一个 JavaScript函数作为一个对象的方法来调用,当一个函数被保存为一个对象的属性是,我们就把它称为方法,例如上文的  obj  对象里的  show  ,当一个方法被调用时,函数体里面的   this  就会绑定到这个对象,例如上文的 show 里面的  this  。方法调用模式也很容易辨别:obj.show(),对象名 . 属性名 () ;代码的话可以参考上文的  obj  代码 ,博主就不多写了。记住:方法的调用是可以在函数体内通过  this  访问自己所属的那个对象的。

三、构造器调用模式

  博主认为构造器调用模式是相对于其他模式来说较为复杂点的调用模式了。通过关键字  new  可以把一个函数作为构造器来调用。关键字  new  可以改变函数的返回值:

function func2(name){
    this.name = name;
}

name;   //undefined

//普通函数调用模式
var foo = func2(‘afei‘);
foo;  //undefined
name;   //afei

//构造器调用模式
var bar = new func2(‘lizefei‘);bar.__proto__ === func2.prototype;  //true
bar;  //{name:‘lizefei‘}
bar.name;  //‘lizefei‘

  在上示代码中我们声明了一个函数 func2 ,分别用两种不同的调用模式去调用它。因为函数  func2  并没有显式返回值,所以作为普通函数去调用时,它什么也没有返回,所以  foo  的值是  undefined  。因为普通调用模式的   this   是指向 全局环境   window  的,所以  func2(‘afei‘);  后,全局环境下就多了一个  name 变量且等于 ‘afei‘。

  func2  作为构造器调用时,我们可以看到,它返回的是一个对象,因为关键字  new  使得函数在调用是发生了如下的特殊变化:

  1.   创建了一个新对象,而且这个新对象是链接到 func2  的  prototype  属性的
  2.   把函数里的  this  指向了这个新对象
  3.   如果没有显式的返回值,新对象作为构造器func2的返回值进行返回(所以bar 是 {name:‘lizefei‘})

  这样子我们就可以看出构造器的作用:通过函数的调用来初始化新创建出来的对象。在JavaScript的面向对象编程里面,这个可是相当重要的。

  因为在函数的声明上,在未来作为构造器调用的函数和普通函数的声明没什么区别,所以导致后来的开发者很容易因为调用模式的错误导致程序出问题。所以开发者们都默契地约定,用来做构造器调用的函数的函数名的第一个字符应该大写,例如:Person,People。这样子后来的开发者一看到函数名就知道要用构造器调用模式调用此函数了。

四、使用apply()和call()方法调用

  这种调用的模式是为了更灵活控制函数运行的上下文环境而诞生的。简单的说就是为了灵活控制函数体内  this  的值。

  apply 和 call这两个方法的第一个参数都是要传递被函数上下文的对象(简单点说就是要绑定给函数  this  的对象)。其他参数就有所不同了:

  apply方法的第二个参数是一个数组,数组里面的值将作为函数调用的参数;

  call方法,从第二个参数起(包括第二个参数),剩下的参数都是作为函数调用的参数;

  让我们看看栗子:

var obj = {
    name :‘afei‘
}
function say(ag1,ag2){
    console.log(ag1+‘:‘+ag2+" "+ this.name);
}
say.apply(obj,[‘apply方法‘,‘hello‘]); //apply方法:hello afei
say.call(obj,‘call方法‘,‘hi‘); //call方法:hi afei

  正如栗子所示,我们把对象 obj  作为函数  say  的上下文来调用函数  say  ,所以函数里的  this  是指向 对象  obj  的。在apply方法里,我们通过数组  [‘apply方法‘,‘hello‘]  给  say  方法传递了两个参数(‘apply方法‘ 和 ‘hello‘),所以打印出来是:  apply方法:hello afei。

  同理  call 也是一样,而且函数传递的方式通过上面的代码也一目了然我,博主就不多做解释了。

  另外,博主还听说apply和call这两个方法除了传递参数的方式不一样,执行的速度还是apply 比 call 要快呢。不过博主就没有实验过。

五、总结

  在JavaScript里面,函数只要的调用模式就是这几种了(在ES6里面还有一种很奇怪很特殊的函数调用模式,叫做’标签模板‘,在这里博主也不多说了,有空另更),只要掌握了这几种主要的调用模式,那么日后再也不用担心  this 的值变来变去了。

  上文如果有漏的、有错误的地方,望各位小伙伴指出,小弟虚心向学。

ps:转载请标明出处  http://www.cnblogs.com/afeihome/

时间: 2024-10-12 13:14:55

JavaScript函数的各种调用模式的相关文章

C#代码与JAVASCRIPT函数的相互调用

问:1.如何在JavaScript访问C#函数?2.如何在JavaScript访问C#变量?3.如何在C#中访问JavaScript的已有变量?4.如何在C#中访问JavaScript函数? 问题1答案如下:javaScript函数中执行C#代码中的函数:方法一:1.首先建立一个按钮,在后台将调用或处理的内容写入button_click中;        2.在前台写一个js函数,内容为document.getElementById("btn1").click();        3.

JavaScript 函数定义和调用

普通的函数定义方法: function abs(x):{ if (x >= 0){ return x; }else { return -x ; } } 两种方法是等价的 var abs = function (x):{ if (x >= 0){ return x; }else { return -x ; }; arguments JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数.arguments类似Array但它

JavaScript函数定义和调用 变量作用域

本文是笔者在看廖雪峰老师JavaScript教程时的个人总结 JavaScript中函数定义可以是这样的格式 function 函数名(参数) { 函数体 } 也可以是这样的格式 var 函数名 = function (参数) { 函数体 }; 关键字一:arguments 获取全部参数 只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数.arguments类似Array但它不是一个Array.第一个参数是arguments[0]....[n] 关键字二:rest 获取 获取除了已定

JavaScript函数参数与调用

函数调用: /*    1.    函数调用        */      var temp = distance(0,1,2,3);        /*    2.    方法调用        */      this.CName = "全局";      var o = {            CName:"o类",            m:function(){                  var self = this;             

JavaScript——函数定义和调用

1.定义函数 定义方式一 绝对值函数 function abs(x){ if(x>=0){ return x; }else{ return -x; } } 上述abs()函数的定义如下: function指出这是一个函数定义: abs是函数的名称: (x)括号内列出函数的参数,多个参数以,分隔: { ... }之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句. 注意: 函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回.因此,函数内部通过条件判断和循环可以

JavaScript函数的调用模式有哪些?

函数是JavaScript 世界里的第一公民,换句话来说,就是我们如果可以精通 JavaScript 函数的使用,那么对JavaScript 的运用可以更游刃有余了.熟悉 JavaScript 的人应该都知道,同样的函数,以不同的方式调用的话,受影响最大的应该是  this  .下面我们来说说 JavaScript 函数的各种调用模式,希望对大家 学习javascript有所帮助. 一.普通函数的调用模式 所谓普通函数的调用模式,也是JavaScript 函数的最简单的一种调用模式,直接就是函数

javascript中函数的四种调用模式详解

介绍函数四种调用模式前,我们先来了解一下函数和方法的概念,其实函数和方法本质是一样,就是称呼不一样而已.函数:如果一个函数与任何对象关系,就称该函数为函数.方法:如果一个函数作为一个对象属性存在,我们就称之为方法.接下来就可以开始今天的主体. 1.函数调用模式. 就是通过函数来调用,规范写法为:function fn(){} fn(); 函数中this的指向->window.案例如下: var age = 38; var obj = { age: 18, getAge: function() {

JavaScript中函数的四种调用模式

理解函数的四种调用方法,可以有效的帮助我们分析和理解JavaScript代码.但是经常有人分不清楚或者不理解这四种调用模式,在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而非像C#或其他描述性语言那样仅仅作为一个模块来使用.函数有四种调用模式,分别是:1.函数调用形式 2.方法调用形式 3.构造器调用形式 4.上下文调用形式(apply,call)这里所有的调用模式中,最主要的区别在于关键字 this 的意义.下面分别介绍这几种调用形式. 一.函数调用形式

JavaScript (JS) 函数补充 (含arguments、eval()、四种调用模式)

1. 程序异常 ① try-catch语法    测试异常 try-catch语法代码如下: try { 异常代码;     try中可以承重异常代码, console.log("try")  出现异常代码后,正确代码不会执行 } catch (e) { console.log("e:"+e);  try中出现异常在e中展现出来 console.log("catch");  只有try中出现异常才执行这段代码 } finally { consol