JS中的this对象详解

 

JS中this关键字很常见,但是它似乎变幻莫测,让人抓狂。这篇文章就来揭示其中的奥秘。

借助阮一峰老师的话:它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。这句话看似平常,可是要非常注意三个字:“运行时”,这说明this关键字只与函数的执行环境有关,而与声明环境没有关系。也就是这个this到底代表的是什么对象要等到函数运行时才知道,有点类似函数定义时的参数列表只在函数调用时才传入真正的对象。理解了这一点对后面this关键字规律的掌握有很大帮助。

this关键字虽然会根据环境变化,但是它始终代表的是调用当前函数的那个对象。这就引出了JS中函数调用的问题。在JS中调用函数的模式可以分为4种: 方法调用模式、函数调用模式、构造器调用模式、apply调用模式。这些模式在如何初始化关键参数this上存在差异。

一、方法调用模式

当函数被保存为一个对象的属性时,它就可称为这个对象的方法。当一个方法被调用时,this被绑定到这个对象上。如果调用表达式包含一个提取属性的动作(. 或 []),那么它被称为方法调用。例如:

1
2
3
4
5
6
7
8
var name = "window";
var obj = {
    name: "kxy",
    sayName: function() {
        console.log(this.name);
    }
};
obj.sayName();  //kxy

sayName函数作为对象obj的方法调用,所以函数体中的this就代表obj对象。

二、函数调用模式

当一个函数并非一个对象的属性时,那么它就是被当做函数来调用的。在此种模式下,this被绑定为全局对象,在浏览器环境下就是window对象。例如:

1
2
3
4
5
var name = "window";
function sayName() {
    console.log(this.name);
}
sayName();

sayName以函数调用模式调用,所以函数体中的this代表window对象。

三、构造函数模式

如果在一个函数前面加上new关键字来调用,那么就会创建一个连接到该函数的prototype成员的新对象,同时,this会被绑定到这个新对象上。这种情况下,这个函数就可以成为此对象的构造函数。例如:

1
2
3
4
5
function Obj() {
    this.name = "kxy";
}
var person = new Obj();
console.log(person.name);   //kxy

Obj作为构造函数被调用,函数体内的this被绑定为新创建的对象person。

四、apply调用模式

在JS中,函数也是对象,所有函数对象都有两个方法:apply和call,这两个方法可以让我们构建一个参数数组传递给调用函数,也允许我们改变this的值。例如:

1
2
3
4
5
6
7
8
9
10
var name = "window";
var person = {
    name: "kxy"
};
function sayName() {
    console.log(this.name);
}
sayName();    //window
sayName.apply(person);   //kxy
sayName.apply();    //window

当以函数调用模式调用sayName时,this代表window;当用apply模式调用sayName,并给它传入的第一个参数为person时,this被绑定到person对象上。如果不给apply传入任何参数,则this代表window。

自此,函数调用的4种模式就都介绍完了,this的绑定规律也就是以上几种,万变不离其宗。为了简单明了的介绍4种模式,以上的例子都比较简单,那么下面就跟我一起做一个稍复杂的练习,检验下自己是否真正掌握了this绑定对象的方法吧!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var name = "window";
function showName() {
    console.log(this.name);
}
var person1 = {
    name: "kxy",
    sayName: showName
}
var person2 = {
    name: "Jake",
    sayName: function() {
        var fun = person1.sayName;
        fun();
    }
}
person1.sayName();    //kxy
person2.sayName();    //window

首先心中时刻提醒自己this是在函数执行时被绑定的,不要被任何赋值语句打乱阵脚。

先看第一个执行语句:person1.sayName(); 首先确定这是方法调用模式,对象为person1,再看sayName被赋值为全局函数对象showName,在showName执行时,this绑定的是person1,所以结果为”kxy”。

再看第二个执行语句:person2.sayName(); 这还是方法调用模式,对象为person2,调用的是它的sayName方法。再看sayName函数体,发现函数体最终执行的函数是fun,fun是用函数调用模式调用的。而fun最终也被赋值为showName函数,因为fun是用函数调用模式调用的,所以这里的this绑定为window,结果为”window“。

转js中this指向的简明解答的更多相关文章

  1. JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解

      前  言 JRedu 学过程序语言的都知道,我们的程序语言进化是从"面向机器".到"面向过程".再到"面向对象"一步步的发展而来.类似于 ...

  2. 关于js中this指向的理解总结!

    关于js中this指向的理解! this是什么?定义:this是包含它的函数作为方法被调用时所属的对象. 首先,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁 ...

  3. 前端js中this指向及改变this指向的方法

    js中this指向是一个难点,花了很长时间来整理和学习相关的知识点. 一. this this是JS中的关键字, 它始终指向了一个对象, this是一个指针; 参考博文: JavaScript函数中的 ...

  4. js中this指向的三种情况

    js中this指向的几种情况一.全局作用域或者普通函数自执行中this指向全局对象window,普通函数的自执行会进行预编译,然后预编译this的指向是window //全局作用域 console.l ...

  5. JS中this指向的更改

    JS中this指向的更改 JavaScript 中 this 的指向问题 前面已经总结过,但在实际开中, 很多场景都需要改变 this 的指向. 现在我们讨论更改 this 指向的问题. call更改 ...

  6. 关于js中this指向的总结

    js中this指向问题一直是个坑,之前一直是懵懵懂懂的,大概知道一点,但一直不知道各种情况下指向有什么区别,今天亲自动手测试了下this的指向. 1.在对象中的this对象中的this指向我们创建的对 ...

  7. 如何理解JS中this指向的问题

    首先,用一句话解释this,就是:指向执行当前函数的对象. 当前执行,理解一下,也就是说this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定.this到底指向谁?this的最终指向的 ...

  8. 关于js中this指向的问题

    this的绑定规则有4种 默认绑定 隐性绑定 显性绑定 new绑定 this绑定优先级 new 绑定 > 显性绑定 > 隐性绑定 > 默认绑定 1.如果函数被new 修饰 this绑 ...

  9. js中this指向学习总结

      在面向对象的语言中(例如Java,C#等),this 含义是明确且具体的,即指向当前对象.一般在编译期绑定. 然而js中this 是在运行期进行绑定的,这是js中this 关键字具备多重含义的本质 ...

随机推荐

  1. swiper

    <!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" ...

  2. JS获取文本值

    var closeBtn=document.getElementById("close_btn"): closeBtn.innerHTML即是文本值,如果要的是数字parseInt ...

  3. Spring知识汇总

    Spring简介 Spring框架由Rod Johnson开发,2004年发布了Spring框架的第一版.Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅 ...

  4. pkg-config

    可以使用pkg-config获取的库需要有一个条件,那就是要求库的提供者,提供一个.pc文件.比如gtk+-2.0的pc文件内容如下: prefix=/usrexec_prefix=/usrlibdi ...

  5. struts2原理理解

    1.  由容器创建HttpServletRequest请求,这个请求经过一系列的过滤器,最终到struts2的核心过滤器(FilterDispatch), 2.  核心过滤器会根据url请求获得Act ...

  6. 【c++】虚基类

    何要使用虚基类: 为何避免多层继承中出项多个公共基类所造成的歧义现象 虚基类用法 派生类继承基类时,加上一个virtual关键词则为虚拟基类继承. 在上图程序运行中,我们发现class bass的构造 ...

  7. adb常用命令

    adb命令的主要用途  1. 运行android设备的shell(命令行).  2.管理模拟器或android设备的映射端口.  3. 安装和卸载应用程序.  4.计算机和android设备之间的上传 ...

  8. SQL Server 显示执行一条语句的执行时间

    set statistics time on执行语句set statistics time off

  9. MongoDB的基础知识

    本人只是软件开发的一个菜鸟,在学习MongoDB,总结了一点自己学习的知识,监督自己学习. 如果文章中有不足的地方,还请大神指点迷津,纠正改错,谢谢. 一.MongoDB简介 MongoDB是一个基于 ...

  10. Ionic打包过程下载Gradle失败的解决方法

      安卓应用现在很多都是基于gradle进行大包,ionic默认的打包命令 cordova  build --release  android 就是使用gradle进行打包,但同时ionic也支持in ...