Javascript 中的 this,是一个高频变量,在很多场景下都会使用,所以总结了一下关于this指向的问题。

如未标明,以下内容是在非严格模式下生效

在函数中 this 到底取何值,是在函数真正被调用执行的时候确定下来的,函数定义的时候确定不了。

因为 this 的取值是函数执行上下文(context)的一部分,每次调用函数,都会产生一个新的执行上下文环境。当代码中使用了 this,这个 this 的值就直接从执行的上下文中获取了,而不会从作用域链中搜寻。

情况一:全局 & 调用普通函数

在全局环境中,this 永远指向 window(浏览器环境下,node环境下指向global)。

console.log(this === window); //true

普通函数在调用时候(注意不是构造函数,前面不加 new),其中的 this 也是指向 window。

var x = 10;function foo(){ console.log(this); //Window console.log(this.x); //10}foo();

情况二:构造函数

所谓的构造函数就是由一个函数 new 出来的对象,一般构造函数的函数名首字母大写,例如像 Object,Function,Array 这些都属于构造函数。

function Foo(){ this.x = 10; console.log(this); //Foo {x:10}}var foo = new Foo();console.log(foo.x); //10

上述代码,如果函数作为构造函数使用,那么其中的 this 就代表它即将 new 出来的对象。

但是如果直接调用 Foo 函数,而不是 new Foo(),那就变成情况1,这时候 Foo() 就变成普通函数。

function Foo(){ this.x = 10; console.log(this); //Window}var foo = Foo();console.log(foo.x); //undefined

情况三:对象方法

如果函数作为对象的方法时,方法中的 this 指向该对象。

var obj = { x: 10, foo: function () { console.log(this); //Object console.log(this.x); //10 }};obj.foo();

注意:若是在对象方法中定义函数,那么情况就不同了。

var obj = { x: 10, foo: function () { function f(){ console.log(this); //Window console.log(this.x); //undefined } f(); }}obj.foo();

可以这么理解:函数 f 虽然是在 obj.foo 内部定义的,但它仍然属于一个普通函数,this 仍指向 window。

在这里,如果想要调用上层作用域中的变量 obj.x,可以使用 self 缓存外部 this 变量。

var obj = { x: 10, foo: function () { var self = this; function f(){ console.log(self); //{x: 10} console.log(self.x); //10 } f(); }}obj.foo();

如果 foo 函数不作为对象方法被调用:

var obj = { x: 10, foo: function () { console.log(this); //Window console.log(this.x); //undefined }};var fn = obj.foo;fn();

obj.foo 被赋值给一个全局变量,并没有作为 obj 的一个属性被调用,那么此时 this 的值是 window。

情况四:构造函数 prototype 属性

function Foo(){ this.x = 10;}Foo.prototype.getX = function () { console.log(this); //Foo {x: 10, getX: function} console.log(this.x); //10}var foo = new Foo();foo.getX();

情况五:函数用 call、apply或者 bind 调用。

var obj = { x: 10}function foo(){ console.log(this); //{x: 10} console.log(this.x); //10}foo.call(obj);foo.apply(obj);foo.bind(obj)();

当一个函数被 call、apply 或者 bind 调用时,this 的值就取传入的对象的值。

情况六:DOM event this

在一个 HTML DOM 事件处理程序里,this 始终指向这个处理程序所绑定的 HTML DOM 节点

function Listener(){  document.getElementById('foo').addEventListener('click', this.handleClick); //这里的 this 指向 Listener 这个对象。不是强调的是这里的 this}Listener.prototype.handleClick = function (event) { console.log(this); //

这个很好理解,就相当于是给函数传参,使 handleClick 运行时上下文改变了,相当于下面这样的代码:

var obj = { x: 10, fn: function() { console.log(this); //Window console.log(this.x); //undefined }};function foo(fn) { fn();} foo(obj.fn);

你也可以用通过 bind 切换上下文:

function Listener(){ document.getElementById('foo').addEventListener('click',this.handleClick.bind(this)); }Listener.prototype.handleClick = function (event) { console.log(this); //Listener {}}var listener = new Listener();document.getElementById('foo').click();

前六种情况其实可以总结为: this 指向调用该方法的对象。

情况七:箭头函数中的 this

当使用箭头函数的时候,情况就有所不同了:箭头函数内部的 this 是词法作用域,由上下文确定。

var obj = { x: 10, foo: function() { var fn = () => { return () => { return () => { console.log(this); //Object {x: 10} console.log(this.x); //10 } } } fn()()(); }}obj.foo();

现在,箭头函数完全修复了 this 的指向,this 总是指向词法作用域,也就是外层调用者 obj。

如果使用箭头函数,以前的这种 hack 写法:var self = this; 就不再需要了。

由于 this 在箭头函数中已经按照词法作用域绑定了,所以,用 call()或者 apply()调用箭头函数时,无法对 this 进行绑定,即传入的第一个参数被忽略。

使用this调用已有的有参构造函数_JavaScript 中的 this 的几种使用场景相关推荐

  1. 使用this调用已有的有参构造函数_加倍提升开发效率,继续深挖一下Lombok的使用

    本篇来接续上一篇文章 Lombok 常规使用介绍,主要介绍一下 Lombok 非常用注解. @Value @Value 是 @Data 中不可变的注解,所有的属性默认都是 private 和 fina ...

  2. java子类要调用父类的无参构造函数

    如果子类要调用父类的无参构造函数,则通过super()调用来实现. 子类的每一个构造方法都必须显式或隐式调用父类的一个构造方法. 如果不显式调用, 则系统隐式调用super(),即父类的无参构造方法( ...

  3. java调用视图如何传参_Spring MVC中 视图 向 控制器 传参(接收方式)

    1.方法一(通过HttpServletRequest方式接收) 1.1.添加servlet的jar包 javax.servlet javax.servlet-api 3.1.0 provided 1. ...

  4. js 闭包函数 构造函数_JavaScript中的闭包,库里函数和酷抽象

    js 闭包函数 构造函数 In this article, we will talk about closures and curried functions and we'll play aroun ...

  5. 警惕!国内已有5000余个网站中招!关于一种大规模的暗链劫持流量的风险提示

    近期,安恒信息中央研究院零壹实验室.回声实验室共同监测发现一种新型全局劫持的暗链植入行为,区别于传统的全局劫持,本次暗链植入手段隐蔽性极强,针对不同访问对象.不同页面设计了不同的响应方式.据不完全统计 ...

  6. 精通在vfp中调用word的方法_word文档中打钩的8种方法!(全网最全)

    我们经常在Word中制作一些填写单的时候,都会输入一些特殊符号,比如方框内打钩,那么这个符号应该怎么输入呢? 接下来,我就给你们介绍几种简单实用的方法 1.直接插入符号 将光标定位于需要打钩的地方,选 ...

  7. c++的构造函数极其调用(无参构造函数,有参构造函数,拷贝构造函数)

    1.c++编译器会自动调用构造函数 //构造函数(与类名相同) //析构函数:没有参数也没有任何返回类型,被自动调用 #include<iostream> using namespace ...

  8. 为什么要写无参构造函数

    今天在码代码时报错: Cannot construct instance of org.tech.arthur.model.domain.DataTestDTO (no Creators, like ...

  9. C++关于默认构造函数和无参构造函数

    C++关于默认构造函数和无参构造函数 默认构造函数 在不提供任何构造函数的情况下,编译器给出一个不带参数的,不包含代码的构造函数. #include<iostream> using nam ...

最新文章

  1. Anaconda安装jieba方法
  2. centos7静默搭建oracle11g,Linux静默安装Oracle方法(centos7+oracle11g)
  3. 并发执行变成串行_网易Java研发面试官眼中的Java并发——安全性、活跃性、性能...
  4. Jexus~docker与它产生了暖味
  5. JWT认证原理、整合springboot实战应用
  6. CJSON之完全基于C库函数的使用
  7. Spring MVC 起步
  8. springboot整合rabbitmq(一)
  9. Html5用户注册页面
  10. 微信红包管理数据库mysql_莫晓东 - 微信红包数据库架构演变
  11. BadBoy安装与使用
  12. JAVA并发编程的书籍及资料
  13. Win硬件 - 西部数据绿盘、蓝盘、黑盘、红盘和紫盘有什么区别?
  14. i217lm网卡驱动linux,【电脑不能上网怎么安装网卡驱动】i217lm网卡驱动xp
  15. 一次UDP收不到问题排查
  16. 同轴电缆阻抗总结(电阻、阻抗、特性阻抗)
  17. 大类资产配置策略(一)恒定混合策略(Constant-mix Strategy)
  18. 鸟人的Android揭秘(4)——Android 源代码编译
  19. 网课答案搜题查询题库接口
  20. qt网络编程之使用cookie和ssl

热门文章

  1. python中什么是主要数据类型_python中基本数据类型是什么
  2. LabVIEW自带函数实现SQL Server操作(下)
  3. mvc 怎么把后台拼接好的div写到前台_五、controller层配置和前台数据crud操作的实现...
  4. Play framework logging设置
  5. 利用Python定时给女友微信发送今日天气情况,异地恋维护感情神器
  6. 北京高院宣判:微信商标案终审驳回上诉 维持原判
  7. hdu 5076 最小割灵活运用
  8. 用C实现的一个Bash脚本
  9. 关于ASPNET_Membership用户被锁的解决
  10. 开源漏洞扫描工具(OWASP-Dependency-Check)探索