zoukankan      html  css  js  c++  java
  • js函数中的this关键字

    关于这个this关键字,也是很多项目中常常被用到的,那么,有人也许会问,干嘛要用this呢,在函数被调用时,直接指明是什么对象在调用不就行了?还整那么个模模糊糊的概念出来干嘛?不过嘛,存在即真理,既然有这么个东西,那也就有他存在的意义,下面来看看吧。

    首先,我们要先回忆一下js函数都有哪几种调用的场合,有如下几种场合:

    1、很常规的调用(即直接调用,其实你发现也是全局调用);

    2、作为某个对象的豆哥方法被调用;

    3、作为构造函数,用来新建某个新对象(object);

    4、很让人头大的apply调用(在实现部分继承的时候经常这么干)。

    好了,一起来看看上述几种情况下this关键字是怎样被玩的出神入化的。

    一、纯粹的函数调用

    这是函数的最通常用法,属于全局性调用,因此this就代表全局对象Global,那么这里Global很多人又很迷惑了,实则在浏览器环境下,Global也即是window对象,global对象是单体内置对象,即不依赖宿主环境的对象,而window对象依赖浏览器。

    看下面这段代码:

    function test(){

      this.name = "dearxiangxiao";

      console.log(this.name );

    }

    test();  //dearxiangxiao

    感觉还是很神奇的,不知不觉test函数里面定义的属性,在外面也可以读取了?对代码做一些修改,如下:

    var name = "xiangxiao";

    function test(){

      this.name  = "dearxiangxiao";

    }

    test();

    alert(name); //  dearxiangxiao

    可以看出,在执行完test函数之后,name的值被改变了,原因何在?这里就是这个调用test的对象是Global在作怪,既然test是被全局对象Global调用的,那么this也就指向Global对象了,全局对象的属性,当然可以读取并修改了,没啥错。

    二、作为对象方法的调用

    函数还可以作为某个对象的方法调用,这时this就指这个上级对象,也来看一段代码:

    function test(){

      console.log("my name is "+this.name + " and my profession is "+this.profession);

    };

    var person = {};

    person .name= "dearxiangxiao";

    person.profession = "projector";

    person.interduce= test;

    person .interduce(); // my name is dearxiangxiao,and my profession is projector

    这里很好理解,既然是person在调用test函数,那么理所应当的this指向的是person实体,也就是前面说的调用函数的上一级对象,它的name和profession 属性当然应该被读取出来了。

    三、作为构造函数调用

    所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象,也来看一段代码,将一中的例子做轻微的修改:

    var name = "xiangxiao";

    function Person(){

      this.name  = "dearxiangxiao";

    }

    var person1 = new Person();

    console.log(name); // xiangxiao

    console.log(person1.name);   //  dearxiangxiao

    可以看出,this指向的对象是刚刚新建的person1,读取出了它的名称dearxiangxiao,而直接打印name变量,值仍然未变,为之前的xiangxiao。这更加表明this指向person1,而不是Global对象。

    四、apply调用

    apply()是函数对象的一个方法,它的作用是改变函数的调用对象(实则是将某某对象的某个方法放到另一个好基友对象那里去执行),它的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。

    关于这个apply,可能大多数人不太喜欢用它,要想调用某个对象直接调用不就好了么?但是应该想到,假如你想调用别人写好的某个方法,某些参数变量却要用到你自己的,怎么办?apply和call就派上用场了,这也是js面向对象思维转换的重要一环,必须理解的(关于apply和call具体详情,请看我的另一篇博文:js面向对象思维转换的一个阶梯:apply和call)。

    下面还是来看个例子吧,这里把三中的例子做一些轻微的修改:

    var name = "xiangxiao";

    function test(){

      console.log(this.name);

    }

    var person1 = new Person();

    person1.name = "dearxiangxiao";

    person1.interduce = test;

    person1.interduce.apply();  // 这里输出的四xiangxiao

    怎么回事,不是说好了的要改变函数的调用对象么?怎么还是被Global调用了?不急不急,来看看apply后面的括号里,没任何东西,默认没有残数时是全局对象Global,因此,此处也就真的是调用出了Global的name变量。那person1.interduce.apply()怎么理解呢?可以这么理解:将person1实体的interduce方法放到Global对象上去执行。

    好了,我们刚刚在前面说了,apply后面括号里的第一个参数,即为this的指向,那么改一改上面的最后一句代码吧,如下:

    person1.interduce.apply(person1); // 这里输出的就是dearxiangxiao

    得到person1的name属性值了,突然冒出个想法,这里person1.interduce.apply(person1) 理解出来貌似很拗口额:将person1实体对象的interduce方法放到person1实体对象上去执行,什么鬼?自己的方法自己直接调用不好么?写成 person1.interduce()就行了噻!!!当然可以,那样更简洁,不过,这就是apply方法的特点所致吧,自己的方法,转一圈回到自己手里被调用了,还给出个冠冕堂皇的解释,哈哈,就不吐槽了,我们还是要看到apply带给我们的诸多好处的。

    这篇博文就是这么多内容了,希望大家会喜欢。

  • 相关阅读:
    linux定时器的使用
    6410 spi总线
    6410 spi 设备驱动
    qtcreator 安装后不能显示菜单
    基于Tiny 6410的内核移植 (NAND FLASH 、UBIFS篇)
    有关ajax跨域问题
    sqlmap的安装
    C# 连接数据库的配置方法
    初识Markdown
    ASP.NET 使用Ueditor富文本编辑器
  • 原文地址:https://www.cnblogs.com/xiangxiao/p/6822997.html
Copyright © 2011-2022 走看看