返回顶部
首页 > 资讯 > 前端开发 > html >JavaScript中如何深入理解this
  • 305
分享到

JavaScript中如何深入理解this

2024-04-02 19:04:59 305人浏览 八月长安
摘要

javascript中如何深入理解this,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。定义this是函数运行时自动生成的内部对象,即调用函数

javascript中如何深入理解this,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

定义

this是函数运行时自动生成的内部对象,即调用函数的那个对象。(不一定很准确的定义,但还算通俗易懂) 在大多数情况下,this的值由函数调用方式决定,它不能在执行期间赋值来设置,它在每次执行下可能都有不同的值。

全局执行环境(outside function)

在全局执行环境中,this一直指向全局对象(global object),不管是在严格模式还是在非严格模式中。

代码1

console.log(this.document === document);   //true  // 在浏览器中,window对象也就是全局对象(global object)  console.log(this === window);   //true  this.a  = 37;  console.log(window.a);   //37

函数执行环境(inside function)

在函数执行环境中,this的值取决于函数的调用方式。

而函数的调用方式主要有4种:

  •  函数直接调用

  •  对象方法调用

  •  构造函数调用

  •  call / apply / bind

  •  箭头函数(es6

函数直接调用

下面的代码在非严格模式执行时,this的值会指向全局对象;而在严格模式中,this的值将会默认为undefined。

代码2

  function f1 () {    return this;  }  console.log(f1() === window);   //true  // in node;  console.log(f1() === global);   //true    function f2 () {    'use strict'    return this;  }  console.log(f1() === undefined);   //true

call / apply / bind 改变this的指向

call / apply

call和apply的用法很像,只是后面参数的传入形式不同。

代码3

function add(c, d) {    return this.a + this.b + c + d;  }  var o = {a: 1, b: 3};  // call的第一个参数 是对象,也就是this的指向对象。后面的参数就是函数arguments对象的成员  add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16  // call的第一个参数 是对象,也就是this的指向对象。后面的参数是数组,数组里的成员也就是函数arguments对象成员  add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

使用call和apply时需要注意的是,当传入的第一个参数的值不是对象时,JavaScript会尝试使用ToObject 操作将其转化为对象。

代码4

function bar() {    console.log(Object.prototype.toString.call(this));  }  bar.call(7); // [object Number]

bind 方法

ECMAScript 5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。

https://developer.mozilla.org/en-US/docs/WEB/JavaScript/Reference/Global_Objects/Function/bind

代码5

function f() {    return this.a;  }  var g = f.bind({a: 'azerty'}); //生成一个绑定函数g  console.log(g()); // azerty  var o = {a: 10, f: f, g: g};  console.log(o.f(), o.g());   //10, azerty  //需要注意的是,绑定函数不可以再bind  var h = g.bind({a: 'foo'});  console.log(h());  //azerty,不会变成foo

对象方法调用

当以对象里的方法的方式调用函数时,它们的 this 是调用该函数的对象.

下面的例子中,当 o.f() 被调用时,函数内的this将绑定到o对象。

var prop = 36;  var o = {    prop: 37,    bar: function() {      return this.prop;    }  };  console.log(o.bar());  //37

构造函数调用

代码6

function Person(name, age) {    this.name = name;    this.age = age;    this.introduce = function () {      console.log('My name is ' + this.name + ', I\'m ' + this.age);    };  }  var Joseph = new Person('Joseph', 19);  Joseph.introduce();  // "My name is Joseph, I'm 19"

由上述代码可以清晰的看到this与被新创建的对象绑定了。

注意:当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this。(这句话看起来比较难理解,我们看下一个例子)。

代码7

function Fn2() {    this.a = 9;  // dead code    return {a: 10};  }  var o = new Fn2(); console.log(o.a);  // 10

这个例子说明了当构造函数返回的是一个对象的话,此时this的值会变成此时返回的对象。‘this.a = 9’成了僵尸代码。

箭头函数

在箭头函数( Arrow functions)中,this的值是封闭执行环境决定的。在全局环境中,那么被赋值为全局对象。

Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

var globalObject = this;  var foo = (() => this);  console.log(foo() === globalObject); // true

更重要的是它与其他情况不同的是,不管函数如何调用,上面this的值一直都是全局对象。call / bind 也不能改变它的值。

代码8

// 作为对象方法被调用  var obj = {foo: foo};  console.log(obj.foo() === globalObject); // true  // 尝试用 call 改变this的值  console.log(foo.call(obj) === globalObject); // true //this的值并未变成obj  // 尝试用 bind 改变this的值  foofoo = foo.bind(obj);  console.log(foo() === globalObject); // true

案例

本文知识点都看完了。让我们看几个案例,检查自己的掌握情况。

例1

var prop = 36;  var o = {    prop: 37,    bar1: function() {      function foo1() {        return this.prop;      }      return foo1;    },    bar2: function() {      var foo2  = (() => this.prop); //ES6箭头函数      return foo2;    } };  console.log('result1:'+o.bar1()()); // result1 ?  console.log('result2:'+o.bar2()()); // result2 ?  var fn2 = o.bar2;  console.log('result3:'+fn2()()); // result3 ?

先揭晓答案:例1 result1 = 36,result2 = 37,result3 = 36。我的理解是,在result1中,o.bar1()执行导致foo函数return到了全局环境中,然后执行就变成了在全局中执行,所以得到的是全局中36的值。result2呢?因为this在箭头函数中。它的值不会改变。所以this仍指向o。那为什么result3又重新变了呢?因为此时‘var fn2 = o.bar2’相当于重新定义了一个函数,而this的值当然也就变为了全局对象。

// 相当于这样  var fn2 = function() {      function foo1() {        return this.prop;      }      return foo1;    }  fn2()();

例2

function sum(a,b) {   return a+b;  };  var o = {   num: 1,    fn: function() {          function handle() {            return this.num = sum(this.num, this.num);          }      handle();    }  };  console.log('result:'+o.fn());  // result ?

同样先揭晓答案:result = undefined,用控制台可以看到此时this指向window,而不是o。这是个比较容易掉进去的坑(一般认为是当初的语言设计错误,被人诟病不少)。看似函数是由对象方法调用的,其实细心的话,我们可以看到。handle函数的执行,前面的没有对象的。这种情况下,this指向全局对象。解决办法也很简单。

// 1、取消 handle函数的定义,直接在对象的方法中使用this  fn2: function() {      this.value = sum(this.value, this.value);  //2  },  ///2、使用变量保存外部函数的this。  fn3: function() {      var that = this;   // that == o      function handle() {          that.value = add(that.value, that.value);      }      handle();  }


看完上述内容,你们掌握JavaScript中如何深入理解this的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网html频道,感谢各位的阅读!

--结束END--

本文标题: JavaScript中如何深入理解this

本文链接: https://lsjlt.com/news/82212.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JavaScript中如何深入理解this
    JavaScript中如何深入理解this,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。定义this是函数运行时自动生成的内部对象,即调用函数...
    99+
    2024-04-02
  • 如何理解JavaScript中的this
    今天就跟大家聊聊有关如何理解JavaScript中的this,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。 JavaSc...
    99+
    2024-04-02
  • 如何深入了解JavaScript中的for循环
    本篇文章给大家分享的是有关如何深入了解JavaScript中的for循环,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。在ECMAScript5...
    99+
    2024-04-02
  • 深入理解函数执行上下文this
    目录JavaScript 中的 this 是什么全局执行上下文中的 this函数执行上下文中的 this1. 通过函数的 call 方法设置2. 通过对象调用方法设置3. 通过构造函...
    99+
    2022-11-13
    函数执行上下文 this 执行上下文 this
  • 如何深入理解select (*)
    这期内容当中小编将会给大家带来有关如何深入理解select count(*),文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。SELECT COUNT( * ) F...
    99+
    2024-04-02
  • JavaScript深入刨析this的指向以及如何修改指向
    目录this方法中对象中隐藏的this严格模式可以改变this指向this 老规矩先看代码: 方法中 function test(){ console.log(this)...
    99+
    2024-04-02
  • Javascript中异步等待的深入理解
    在本文中,我们将探讨async/await对于每个Javascript开发人员来说,异步编程的首选工具。如果您不熟悉javascript,请不要担心,本文将帮助您async/awai...
    99+
    2024-04-02
  • 如何深入理解JavaScript错误和堆栈追踪
    如何深入理解JavaScript错误和堆栈追踪,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。有时候人们并不关注这些细节,但这方面的知识肯定有用...
    99+
    2024-04-02
  • 带你深入了解下this.$nextTick!
    我们先看看nextTick究竟是个啥?console.log(this.$nextTick); // 控制台打印 if(fn){ return nextTick(fn, this); }我们可以看出nextTick就是一个方法,方法有两...
    99+
    2023-05-14
    $nextTick Vue
  • JavaScript中如何使用this
    这篇文章主要介绍JavaScript中如何使用this,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!本文我们介绍下js中this的用法。由上图可得,默认this指向window,而在...
    99+
    2024-04-02
  • 如何深入理解Java中的接口
    今天就跟大家聊聊有关如何深入理解Java中的接口,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、前言前面我们说了抽象类的概述,我们对抽象类也有个认识和理解了,现在我们学习十分重要的...
    99+
    2023-06-21
  • 深入理解JavaScript 变量对象
    目录前言变量对象全局上下文中变量对象函数上下文中的变量对象执行过程预编译代码执行总结练习题前言 在上节《深入 JavaScript 执行上下文栈——Web 前...
    99+
    2024-04-02
  • 深入理解JavaScript事件机制
    目录如何实现一个事件的发布订阅介绍下事件循环宏任务和微任务的区别如何实现一个事件的发布订阅 可以通过以下步骤实现 JavaScript 中的发布-订阅模式: 创建一个事件管理器对象。...
    99+
    2023-05-17
    JavaScript事件机制 JS事件机制
  • 如何理解JavaScript函数this指向问题
    这篇文章给大家介绍如何理解JavaScript函数this指向问题,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、 函数内 this 的指向这些 this的指向,是当调用函数的时候确定的。 调用方式的不同决...
    99+
    2023-06-21
  • 深入了解JavaScript中递归的理解与实现
    目录前言递归的基本理解实例解析求斐波那契数时间复杂度分析空间复杂度分析执行顺序分析前言 我们在写业务代码的时候,或多或少都会遇到需要使用递归的场景,比如在遍历树形结构时。 本文将通过...
    99+
    2024-04-02
  • 如何深入理解Redis事务
    本篇内容主要讲解“如何深入理解Redis事务”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何深入理解Redis事务”吧!Redis可以看成NoSQL类型的数据...
    99+
    2024-04-02
  • 如何深入理解MySQL索引
    这篇文章将为大家详细讲解有关如何深入理解MySQL索引,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。前言当提到MySQL数据库的时候,我们的脑海里会想起几个...
    99+
    2024-04-02
  • 深入理解JavaScript中的Base64编码字符串
    目录初步认识Base64是怎么诞生的基础定义编码方式体积增大= 等号非ASCII码字符编解码方法btoa 和 atob第三方库前端常见应用小图片转码文件读取Canvas生成图片其他总...
    99+
    2023-02-21
    JavaScript Base64编码字符串 JavaScript Base64编码 JavaScript Base64
  • JavaScript深入理解节流与防抖
    目录一、js防抖和节流二、为什么滚动scroll、窗口resize等事件需要优化三、滚动和页面渲染前端性能优化的关系四、防抖Debounce1 防抖Debounce情景2 防抖原理3...
    99+
    2024-04-02
  • 从原生JavaScript到React深入理解
    目录从头开始理解 React原生 JavaScript 和 DOMReact 的基础咱老百姓也能学会的 JSX从头开始理解 React 作者:Stéphane B&ea...
    99+
    2024-04-02
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作