zoukankan      html  css  js  c++  java
  • 深入浅出javascript(八)this、call和apply

    _________此篇日志属于重要记录,长期更新__________

    thiscallapply这三个是进阶JS的重要一步,需要详细的记录。

    ➢ this

    一、作为对象的方法调用。

    当函数作为对象方法被调用时,this指向该对象。

    首先,函数必须作为对象的方法。这句话很关键,因为函数的调用有很多种可能,在后面会展现。示例1-1

            var o = {
                name: 'o',
                get: function () {
                    return this.name;
                }
            }
            console.log(o.get());//输出'o'

    get方法是被对象o调用的,所以this指向o,这是没有异议的。

    现在把这个例子改下,示例1-2

            var o = {
                name: 'o',
                get: function () {
                    return this.name;
                }
            };
            var g = o.get;      //将o的get方法赋给g;
            console.log(g());   //输出空;

    o.get方法赋给g之后,现在这个方法g和原来的对象o已经没有关系了,因为g是全局的,所以它属于window的方法,结果导致方法内的this已经指向window,又,window没有定义name属性,所以输出为空。

    从这两个例子的对比可以看出,this是随机而动的,谁绑定,this就指向谁

    二、做为普通函数调用

    这里所说的普通函数调用主要是为了和狭隘的 ' 对象的方法调用 ' 来区别。因为无论函数怎么调用,它总属于一个对象,因为最外层总有一个window对象。

    如上例所示,将函数赋值给另一个变量,就是将这个函数从对象中 ’ 复制一份 ‘ 出来,结果变成window对象的一个方法,因此this指向window。

    示例2-1

    1.创建变量o,因为是全局的,所以内部的this为window,其内部的g也属于普通函数调用,因此也指向this。

    三、函数到底出现在哪儿?

    函数到底出现在哪里,说的是函数究竟出现在哪种地方,只有将出现的这几种地方弄明白,才能对函数做更深入的了解,总结如下:

    1 普通函数
    2 普通函数内部的普通函数
    3 对象内部
    4 对象内部的函数的内部

    ➢ 四种可能:

    普通函数

    this=window

    普通函数内部的普通函数

    this=window

    对象内部函数

    this=对象

    对象内部函数内部的普通函数

    this=window

    function f() {
      console.log(this);
    };

     

    function f() {
      function g() {
        console.log(this);
      }
    };

     

    var o = {
      get: function () {
        console.log(this);
      }
    };

     

    var o = {
      get: function () {
        function g() {
          console.log(this);
        }
      }
    };

    现在可以推断两条结论:

    一、凡是普通函数都指向window
    二、凡是对象调用都指向对象。(这里的对象是狭隘的对象,即自创建的对象)

    换句话说,凡遇到一个函数,首先两问:

    一、这个函数是普通函数吗?[如果是,则this=window]

    二、这个函数是被对象调用的吗?[如果是,则this=对象]

    ※ 回过头再看前面的一句话:当函数作为对象方法被调用时,this指向该对象,也就可以理解了。

    四、做为构造函数

    做为构造函数比较简单,this指定绑定的对象。仅示例:

            var F = function () {
                this.name = 'F';
            };
            var f=new F();

    ➢ apply和call

     一、概述

    apply就是函数调用,而调用的就是函数fn,也就是说执行fn( )。 apply后面是(对象,参数)。参数可以是数组,可以是类数组。

    所以理解这个apply就是记住两个点:

    1.调用函数fn.
    2.传入对象,如果传入的对象为null,则this=window

    apply概括:调用函数fn,fn需要依赖传入的对象来确定它内部的this到底指向谁。

    示例1-1

            window.name = 'window';
            function f() {
                console.log(this.name);
            }
            f.apply(null);  //输出'window'

    首次接触的时候有点点绕

    示例1-2

            function f() {
                console.log(this.name);
            }
            var o = {
                name: '对象o'
            };
            f.apply(o);

    二、作用

    1、改变this的指向

    首先,这个this指的是谁呢?肯定是fn内部的this。如果函数没有this,那又何谈改变this的指向呢。现在先做一个带有this的函数。

            function f() {
                console.log(this.name);
            }

    this是可以随意绑定的,这就是apply的作用,做个图示例一下:

            function f() {
                console.log(this.name);
            }
            var o = {
                name: 'o'
            };

    如上代码所示,f.apply(o),f内部的this绑定了对象o。

    2、借用其它对象的方法——继承

    这种继承是继承方法中的一种 [ 关于Javascript继承详细,参看记录 ],其实说起来更像是 ‘复制’。即:将父类中的属性复制一份到子类,代码2-1

            /***构造继承最简化的形式***/
    
            //父类
            function subClass() {
                this.name = 'subClass';
            }
            //子类
            function superClass() {
                subClass.call(this);
            }
            var o = new superClass();
            console.log(o.name);    //输出'subclass'

    ➢ 代码解析:

    子类构造函数使用父类.call,并将子类自己的this代入,结果就是将父类的属性 '复制' 了一份给子类。

     3、类数组的使用(重要!)

    补充于2018-10-23 20:12:51


    类数组一个比较常见的例子是arguments。这个东西像数组但又不是数组,如果采用一般的数组方法是不可行的,必须采用数组的call调用。

    示例如下:

    arguments.join(","),#这条语句希望将函数参数用","连接起来形成字符串,但是代码错误不能通过。这里采用Array原型方法调用:

    Array.prototype.join.call(arguments,",");

    这一条的应用比较常用且重要,也是采用call调用的一个比较独特的例子。

    4、

  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/tinaluo/p/6677585.html
Copyright © 2011-2022 走看看