深入浅出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、

原文地址:https://www.cnblogs.com/tinaluo/p/6677585.html